func TestStateSnapshotIterator(t *testing.T) { testDBWrapper.CreateFreshDB(t) stateTrieTestWrapper := newStateTrieTestWrapper(t) stateTrie := stateTrieTestWrapper.stateTrie stateDelta := statemgmt.NewStateDelta() // insert keys stateDelta.Set("chaincodeID1", "key1", []byte("value1"), nil) stateDelta.Set("chaincodeID2", "key2", []byte("value2"), nil) stateDelta.Set("chaincodeID3", "key3", []byte("value3"), nil) stateDelta.Set("chaincodeID4", "key4", []byte("value4"), nil) stateDelta.Set("chaincodeID5", "key5", []byte("value5"), nil) stateDelta.Set("chaincodeID6", "key6", []byte("value6"), nil) stateTrie.PrepareWorkingSet(stateDelta) stateTrieTestWrapper.PersistChangesAndResetInMemoryChanges() //check that the key is persisted testutil.AssertEquals(t, stateTrieTestWrapper.Get("chaincodeID1", "key1"), []byte("value1")) testutil.AssertEquals(t, stateTrieTestWrapper.Get("chaincodeID2", "key2"), []byte("value2")) testutil.AssertEquals(t, stateTrieTestWrapper.Get("chaincodeID3", "key3"), []byte("value3")) testutil.AssertEquals(t, stateTrieTestWrapper.Get("chaincodeID4", "key4"), []byte("value4")) testutil.AssertEquals(t, stateTrieTestWrapper.Get("chaincodeID5", "key5"), []byte("value5")) testutil.AssertEquals(t, stateTrieTestWrapper.Get("chaincodeID6", "key6"), []byte("value6")) // take db snapeshot dbSnapshot := db.GetDBHandle().GetSnapshot() stateDelta1 := statemgmt.NewStateDelta() // delete a few keys stateDelta1.Delete("chaincodeID1", "key1", nil) stateDelta1.Delete("chaincodeID3", "key3", nil) stateDelta1.Delete("chaincodeID4", "key4", nil) stateDelta1.Delete("chaincodeID6", "key6", nil) // update remaining keys stateDelta1.Set("chaincodeID2", "key2", []byte("value2_new"), nil) stateDelta1.Set("chaincodeID5", "key5", []byte("value5_new"), nil) stateTrie.PrepareWorkingSet(stateDelta1) stateTrieTestWrapper.PersistChangesAndResetInMemoryChanges() //check that the keys are updated testutil.AssertNil(t, stateTrieTestWrapper.Get("chaincodeID1", "key1")) testutil.AssertNil(t, stateTrieTestWrapper.Get("chaincodeID3", "key3")) testutil.AssertNil(t, stateTrieTestWrapper.Get("chaincodeID4", "key4")) testutil.AssertNil(t, stateTrieTestWrapper.Get("chaincodeID6", "key6")) testutil.AssertEquals(t, stateTrieTestWrapper.Get("chaincodeID2", "key2"), []byte("value2_new")) testutil.AssertEquals(t, stateTrieTestWrapper.Get("chaincodeID5", "key5"), []byte("value5_new")) itr, err := newStateSnapshotIterator(dbSnapshot) testutil.AssertNoError(t, err, "Error while getting state snapeshot iterator") stateDeltaFromSnapshot := statemgmt.NewStateDelta() for itr.Next() { keyBytes, valueBytes := itr.GetRawKeyValue() t.Logf("key=[%s], value=[%s]", string(keyBytes), string(valueBytes)) chaincodeID, key := statemgmt.DecodeCompositeKey(keyBytes) stateDeltaFromSnapshot.Set(chaincodeID, key, valueBytes, nil) } testutil.AssertEquals(t, stateDelta, stateDeltaFromSnapshot) }
func TestRangeScanIteratorEmptyArray(t *testing.T) { testDBWrapper.CreateFreshDB(t) stateImplTestWrapper := newStateImplTestWrapper(t) stateDelta := statemgmt.NewStateDelta() // insert keys stateDelta.Set("chaincodeID1", "key1", []byte("value1"), nil) stateDelta.Set("chaincodeID1", "key2", []byte{}, nil) stateDelta.Set("chaincodeID1", "key3", []byte{}, nil) stateImplTestWrapper.prepareWorkingSet(stateDelta) stateImplTestWrapper.persistChangesAndResetInMemoryChanges() // test range scan for chaincodeID2 rangeScanItr := stateImplTestWrapper.getRangeScanIterator("chaincodeID1", "key1", "key3") var results = make(map[string][]byte) for rangeScanItr.Next() { key, value := rangeScanItr.GetKeyValue() results[key] = value } t.Logf("Results = %s", results) testutil.AssertEquals(t, len(results), 3) testutil.AssertEquals(t, results["key3"], []byte{}) rangeScanItr.Close() }
func TestStateTrie_ComputeHash_AllInMemory_NoContents(t *testing.T) { testDBWrapper.CleanDB(t) stateTrie := NewStateTrie() stateTrieTestWrapper := &stateTrieTestWrapper{stateTrie, t} hash := stateTrieTestWrapper.PrepareWorkingSetAndComputeCryptoHash(statemgmt.NewStateDelta()) testutil.AssertEquals(t, hash, nil) }
// NewState constructs a new State. This Initializes encapsulated state implementation func NewState() *State { initConfig() logger.Infof("Initializing state implementation [%s]", stateImplName) switch stateImplName { case buckettreeType: stateImpl = buckettree.NewStateImpl() case trieType: stateImpl = trie.NewStateImpl() case rawType: stateImpl = raw.NewStateImpl() default: panic("Should not reach here. Configs should have checked for the stateImplName being a valid names ") } err := stateImpl.Initialize(stateImplConfigs) if err != nil { panic(fmt.Errorf("Error during initialization of state implementation: %s", err)) } return &State{stateImpl, statemgmt.NewStateDelta(), statemgmt.NewStateDelta(), "", make(map[string][]byte), false, uint64(deltaHistorySize)} }
// FetchStateDeltaFromDB fetches the StateDelta corrsponding to given blockNumber func (state *State) FetchStateDeltaFromDB(blockNumber uint64) (*statemgmt.StateDelta, error) { stateDeltaBytes, err := db.GetDBHandle().GetFromStateDeltaCF(encodeStateDeltaKey(blockNumber)) if err != nil { return nil, err } if stateDeltaBytes == nil { return nil, nil } stateDelta := statemgmt.NewStateDelta() stateDelta.Unmarshal(stateDeltaBytes) return stateDelta, nil }
func TestStateTrie_GetSet_WithDB(t *testing.T) { testDBWrapper.CreateFreshDB(t) stateTrie := NewStateTrie() stateTrieTestWrapper := &stateTrieTestWrapper{stateTrie, t} stateDelta := statemgmt.NewStateDelta() stateDelta.Set("chaincodeID1", "key1", []byte("value1"), nil) stateDelta.Set("chaincodeID1", "key2", []byte("value2"), nil) stateDelta.Set("chaincodeID2", "key3", []byte("value3"), nil) stateDelta.Set("chaincodeID2", "key4", []byte("value4"), nil) stateTrieTestWrapper.PrepareWorkingSetAndComputeCryptoHash(stateDelta) stateTrieTestWrapper.PersistChangesAndResetInMemoryChanges() testutil.AssertEquals(t, stateTrieTestWrapper.Get("chaincodeID1", "key1"), []byte("value1")) }
func testGetRootHashes(t *testing.T, enableBlockCache bool) ([]byte, []byte, []byte, []byte) { // number of buckets at each level 26,9,3,1 testHasher, stateImplTestWrapper, stateDelta := createFreshDBAndInitTestStateImplWithCustomHasher(t, 26, 3) // populate hash fucntion such that they intersect at higher level buckets testHasher.populate("chaincodeID1", "key1", 1) testHasher.populate("chaincodeID2", "key2", 15) testHasher.populate("chaincodeID3", "key3", 26) if !enableBlockCache { stateImplTestWrapper.stateImpl.bucketCache = newBucketCache(0) } stateDelta.Set("chaincodeID1", "key1", []byte("value1"), nil) stateDelta.Set("chaincodeID2", "key2", []byte("value2"), nil) stateDelta.Set("chaincodeID3", "key3", []byte("value3"), nil) rootHash1 := stateImplTestWrapper.prepareWorkingSetAndComputeCryptoHash(stateDelta) stateImplTestWrapper.persistChangesAndResetInMemoryChanges() stateDelta = statemgmt.NewStateDelta() stateDelta.Set("chaincodeID1", "key1", []byte("value1_new"), nil) rootHash2 := stateImplTestWrapper.prepareWorkingSetAndComputeCryptoHash(stateDelta) stateImplTestWrapper.persistChangesAndResetInMemoryChanges() stateDelta = statemgmt.NewStateDelta() stateDelta.Delete("chaincodeID2", "key2", nil) rootHash3 := stateImplTestWrapper.prepareWorkingSetAndComputeCryptoHash(stateDelta) stateImplTestWrapper.persistChangesAndResetInMemoryChanges() if enableBlockCache { stateImplTestWrapper.stateImpl.bucketCache = newBucketCache(20) stateImplTestWrapper.stateImpl.bucketCache.loadAllBucketNodesFromDB() } stateDelta = statemgmt.NewStateDelta() stateDelta.Set("chaincodeID3", "key3", []byte("value3_new"), nil) rootHash4 := stateImplTestWrapper.prepareWorkingSetAndComputeCryptoHash(stateDelta) stateImplTestWrapper.persistChangesAndResetInMemoryChanges() return rootHash1, rootHash2, rootHash3, rootHash4 }
// sendBlocks sends the blocks based upon the supplied SyncBlockRange over the stream. func (d *Handler) sendStateSnapshot(syncStateSnapshotRequest *pb.SyncStateSnapshotRequest) { peerLogger.Debugf("Sending state snapshot with correlationId = %d", syncStateSnapshotRequest.CorrelationId) snapshot, err := d.Coordinator.GetStateSnapshot() if err != nil { peerLogger.Errorf("Error getting snapshot: %s", err) return } defer snapshot.Release() // Iterate over the state deltas and send to requestor currBlockNumber := snapshot.GetBlockNumber() var sequence uint64 // Loop through and send the Deltas for i := 0; snapshot.Next(); i++ { delta := statemgmt.NewStateDelta() k, v := snapshot.GetRawKeyValue() cID, kID := statemgmt.DecodeCompositeKey(k) delta.Set(cID, kID, v, nil) deltaAsBytes := delta.Marshal() // Encode a SyncStateSnapsot into the payload sequence = uint64(i) syncStateSnapshot := &pb.SyncStateSnapshot{Delta: deltaAsBytes, Sequence: sequence, BlockNumber: currBlockNumber, Request: syncStateSnapshotRequest} syncStateSnapshotBytes, err := proto.Marshal(syncStateSnapshot) if err != nil { peerLogger.Errorf("Error marshalling syncStateSnapsot for BlockNum = %d: %s", currBlockNumber, err) break } if err := d.SendMessage(&pb.Message{Type: pb.Message_SYNC_STATE_SNAPSHOT, Payload: syncStateSnapshotBytes}); err != nil { peerLogger.Errorf("Error sending syncStateSnapsot for BlockNum = %d: %s", currBlockNumber, err) break } } // Now send the terminating message syncStateSnapshot := &pb.SyncStateSnapshot{Delta: []byte{}, Sequence: sequence + 1, BlockNumber: currBlockNumber, Request: syncStateSnapshotRequest} syncStateSnapshotBytes, err := proto.Marshal(syncStateSnapshot) if err != nil { peerLogger.Errorf("Error marshalling terminating syncStateSnapsot message for correlationId = %d, BlockNum = %d: %s", syncStateSnapshotRequest.CorrelationId, currBlockNumber, err) return } if err := d.SendMessage(&pb.Message{Type: pb.Message_SYNC_STATE_SNAPSHOT, Payload: syncStateSnapshotBytes}); err != nil { peerLogger.Errorf("Error sending terminating syncStateSnapsot for correlationId = %d, BlockNum = %d: %s", syncStateSnapshotRequest.CorrelationId, currBlockNumber, err) return } }
func createFreshDBAndInitTestStateImplWithCustomHasher(t testing.TB, numBuckets int, maxGroupingAtEachLevel int) (*testHasher, *stateImplTestWrapper, *statemgmt.StateDelta) { testHasher := newTestHasher() configMap := map[string]interface{}{ ConfigNumBuckets: numBuckets, ConfigMaxGroupingAtEachLevel: maxGroupingAtEachLevel, ConfigHashFunction: testHasher.getHashFunction(), } testDBWrapper.CleanDB(t) stateImpl := NewStateImpl() stateImpl.Initialize(configMap) stateImplTestWrapper := &stateImplTestWrapper{configMap, stateImpl, t} stateDelta := statemgmt.NewStateDelta() return testHasher, stateImplTestWrapper, stateDelta }
func TestStateImpl_ComputeHash_DB_3(t *testing.T) { // simple test... not using custom hasher conf = newConfig(DefaultNumBuckets, DefaultMaxGroupingAtEachLevel, fnvHash) testDBWrapper.CreateFreshDB(t) stateImplTestWrapper := newStateImplTestWrapper(t) stateImpl := stateImplTestWrapper.stateImpl stateDelta := statemgmt.NewStateDelta() stateDelta.Set("chaincode1", "key1", []byte("value1"), nil) stateDelta.Set("chaincode2", "key2", []byte("value2"), nil) stateDelta.Set("chaincode3", "key3", []byte("value3"), nil) stateImpl.PrepareWorkingSet(stateDelta) hash1 := stateImplTestWrapper.computeCryptoHash() stateImplTestWrapper.persistChangesAndResetInMemoryChanges() stateDelta = statemgmt.NewStateDelta() stateDelta.Delete("chaincode1", "key1", nil) stateDelta.Delete("chaincode2", "key2", nil) stateDelta.Delete("chaincode3", "key3", nil) stateImpl.PrepareWorkingSet(stateDelta) hash2 := stateImplTestWrapper.computeCryptoHash() stateImplTestWrapper.persistChangesAndResetInMemoryChanges() testutil.AssertNotEquals(t, hash1, hash2) testutil.AssertNil(t, hash2) }
func TestDataNodesDelta(t *testing.T) { conf = newConfig(26, 3, fnvHash) stateDelta := statemgmt.NewStateDelta() stateDelta.Set("chaincodeID1", "key1", []byte("value1_1"), nil) stateDelta.Set("chaincodeID1", "key2", []byte("value1_2"), nil) stateDelta.Set("chaincodeID2", "key1", []byte("value2_1"), nil) stateDelta.Set("chaincodeID2", "key2", []byte("value2_2"), nil) dataNodesDelta := newDataNodesDelta(stateDelta) affectedBuckets := dataNodesDelta.getAffectedBuckets() testutil.AssertContains(t, affectedBuckets, newDataKey("chaincodeID1", "key1").getBucketKey()) testutil.AssertContains(t, affectedBuckets, newDataKey("chaincodeID1", "key2").getBucketKey()) testutil.AssertContains(t, affectedBuckets, newDataKey("chaincodeID2", "key1").getBucketKey()) testutil.AssertContains(t, affectedBuckets, newDataKey("chaincodeID2", "key2").getBucketKey()) }
func TestStateImpl_DB_EmptyArrayValues(t *testing.T) { testDBWrapper.CreateFreshDB(t) stateImplTestWrapper := newStateImplTestWrapper(t) stateImpl := stateImplTestWrapper.stateImpl stateDelta := statemgmt.NewStateDelta() stateDelta.Set("chaincode1", "key1", []byte{}, nil) stateImpl.PrepareWorkingSet(stateDelta) stateImplTestWrapper.persistChangesAndResetInMemoryChanges() emptyBytes := stateImplTestWrapper.get("chaincode1", "key1") if emptyBytes == nil || len(emptyBytes) != 0 { t.Fatalf("Expected an empty byte array. found = %#v", emptyBytes) } nilVal := stateImplTestWrapper.get("chaincodeID3", "non-existing-key") if nilVal != nil { t.Fatalf("Expected a nil. found = %#v", nilVal) } }
// TxFinish marks the completion of on-going tx. If txID is not same as of the on-going tx, this call panics func (state *State) TxFinish(txID string, txSuccessful bool) { logger.Debugf("txFinish() for txId [%s], txSuccessful=[%t]", txID, txSuccessful) if state.currentTxID != txID { panic(fmt.Errorf("Different txId in tx-begin [%s] and tx-finish [%s]", state.currentTxID, txID)) } if txSuccessful { if !state.currentTxStateDelta.IsEmpty() { logger.Debugf("txFinish() for txId [%s] merging state changes", txID) state.stateDelta.ApplyChanges(state.currentTxStateDelta) state.txStateDeltaHash[txID] = state.currentTxStateDelta.ComputeCryptoHash() state.updateStateImpl = true } else { state.txStateDeltaHash[txID] = nil } } state.currentTxStateDelta = statemgmt.NewStateDelta() state.currentTxID = "" }
func TestStateSnapshotIterator(t *testing.T) { testDBWrapper.CleanDB(t) stateImplTestWrapper := newStateImplTestWrapper(t) stateDelta := statemgmt.NewStateDelta() // insert keys stateDelta.Set("chaincodeID1", "key1", []byte("value1"), nil) stateDelta.Set("chaincodeID2", "key2", []byte("value2"), nil) stateDelta.Set("chaincodeID3", "key3", []byte("value3"), nil) stateDelta.Set("chaincodeID4", "key4", []byte("value4"), nil) stateDelta.Set("chaincodeID5", "key5", []byte("value5"), nil) stateDelta.Set("chaincodeID6", "key6", []byte("value6"), nil) stateImplTestWrapper.prepareWorkingSet(stateDelta) stateImplTestWrapper.persistChangesAndResetInMemoryChanges() //check that the key is persisted testutil.AssertEquals(t, stateImplTestWrapper.get("chaincodeID5", "key5"), []byte("value5")) // take db snapeshot dbSnapshot := db.GetDBHandle().GetSnapshot() // delete keys stateDelta.Delete("chaincodeID1", "key1", nil) stateDelta.Delete("chaincodeID2", "key2", nil) stateDelta.Delete("chaincodeID3", "key3", nil) stateDelta.Delete("chaincodeID4", "key4", nil) stateDelta.Delete("chaincodeID5", "key5", nil) stateDelta.Delete("chaincodeID6", "key6", nil) stateImplTestWrapper.prepareWorkingSet(stateDelta) stateImplTestWrapper.persistChangesAndResetInMemoryChanges() //check that the key is deleted testutil.AssertNil(t, stateImplTestWrapper.get("chaincodeID5", "key5")) itr, err := newStateSnapshotIterator(dbSnapshot) testutil.AssertNoError(t, err, "Error while getting state snapeshot iterator") numKeys := 0 for itr.Next() { key, value := itr.GetRawKeyValue() t.Logf("key=[%s], value=[%s]", string(key), string(value)) numKeys++ } testutil.AssertEquals(t, numKeys, 6) }
func TestStateTrie_ComputeHash_AllInMemory(t *testing.T) { testDBWrapper.CleanDB(t) stateTrie := NewStateTrie() stateTrieTestWrapper := &stateTrieTestWrapper{stateTrie, t} stateDelta := statemgmt.NewStateDelta() // Test1 - Add a few keys stateDelta.Set("chaincodeID1", "key1", []byte("value1"), nil) stateDelta.Set("chaincodeID1", "key2", []byte("value2"), nil) stateDelta.Set("chaincodeID2", "key3", []byte("value3"), nil) stateDelta.Set("chaincodeID2", "key4", []byte("value4"), nil) stateTrieTestWrapper.PrepareWorkingSetAndComputeCryptoHash(stateDelta) rootHash1 := stateTrieTestWrapper.PrepareWorkingSetAndComputeCryptoHash(stateDelta) hash1 := expectedCryptoHashForTest(newTrieKey("chaincodeID1", "key1"), []byte("value1")) hash2 := expectedCryptoHashForTest(newTrieKey("chaincodeID1", "key2"), []byte("value2")) hash3 := expectedCryptoHashForTest(newTrieKey("chaincodeID2", "key3"), []byte("value3")) hash4 := expectedCryptoHashForTest(newTrieKey("chaincodeID2", "key4"), []byte("value4")) hash1Hash2 := expectedCryptoHashForTest(nil, nil, hash1, hash2) hash3Hash4 := expectedCryptoHashForTest(nil, nil, hash3, hash4) expectedRootHash1 := expectedCryptoHashForTest(nil, nil, hash1Hash2, hash3Hash4) testutil.AssertEquals(t, rootHash1, expectedRootHash1) stateTrie.ClearWorkingSet(true) //Test2 - Add one more key t.Logf("-- Add one more key exiting key --- ") stateDelta.Set("chaincodeID3", "key5", []byte("value5"), nil) rootHash2 := stateTrieTestWrapper.PrepareWorkingSetAndComputeCryptoHash(stateDelta) hash5 := expectedCryptoHashForTest(newTrieKey("chaincodeID3", "key5"), []byte("value5")) expectedRootHash2 := expectedCryptoHashForTest(nil, nil, hash1Hash2, hash3Hash4, hash5) testutil.AssertEquals(t, rootHash2, expectedRootHash2) stateTrie.ClearWorkingSet(true) // Test3 - Remove one of the existing keys t.Logf("-- Remove an exiting key --- ") stateDelta.Delete("chaincodeID2", "key4", nil) rootHash3 := stateTrieTestWrapper.PrepareWorkingSetAndComputeCryptoHash(stateDelta) expectedRootHash3 := expectedCryptoHashForTest(nil, nil, hash1Hash2, hash3, hash5) testutil.AssertEquals(t, rootHash3, expectedRootHash3) stateTrie.ClearWorkingSet(true) }
func TestStateTrie_GetSet_WithDB(t *testing.T) { testDBWrapper.CleanDB(t) stateTrie := NewStateTrie() stateTrieTestWrapper := &stateTrieTestWrapper{stateTrie, t} stateDelta := statemgmt.NewStateDelta() stateDelta.Set("chaincodeID1", "key1", []byte("value1"), nil) stateDelta.Set("chaincodeID1", "key2", []byte("value2"), nil) stateDelta.Set("chaincodeID2", "key3", []byte("value3"), nil) stateDelta.Set("chaincodeID2", "key4", []byte("value4"), nil) stateDelta.Set("chaincodeID3", "key5", []byte{}, nil) stateTrieTestWrapper.PrepareWorkingSetAndComputeCryptoHash(stateDelta) stateTrieTestWrapper.PersistChangesAndResetInMemoryChanges() testutil.AssertEquals(t, stateTrieTestWrapper.Get("chaincodeID1", "key1"), []byte("value1")) emptyBytes := stateTrieTestWrapper.Get("chaincodeID3", "key5") if emptyBytes == nil || len(emptyBytes) != 0 { t.Fatalf("Expected an empty byte array. found = %#v", emptyBytes) } nilVal := stateTrieTestWrapper.Get("chaincodeID3", "non-existing-key") if nilVal != nil { t.Fatalf("Expected a nil. found = %#v", nilVal) } }
Expect(err).To(BeNil()) err = ledgerPtr.CommitTxBatch(2, []*protos.Transaction{tx}, nil, []byte("proof")) Expect(err).To(BeNil()) state, _ := ledgerPtr.GetState("chaincode1", "key1", true) Expect(state).To(BeNil()) state, _ = ledgerPtr.GetState("chaincode2", "key2", true) Expect(state).To(BeNil()) state, _ = ledgerPtr.GetState("chaincode3", "key3", true) Expect(state).To(BeNil()) hash2, err = ledgerPtr.GetTempStateHash() Expect(err).To(BeNil()) Expect(bytes.Compare(hash1, hash2)).ToNot(Equal(0)) // put key/values from the snapshot back in the DB //var keys, values [][]byte delta := statemgmt.NewStateDelta() for i := 0; snapshot.Next(); i++ { k, v := snapshot.GetRawKeyValue() cID, keyID := statemgmt.DecodeCompositeKey(k) delta.Set(cID, keyID, v, nil) } ledgerPtr.ApplyStateDelta(1, delta) ledgerPtr.CommitStateDelta(1) }) It("should return restored state", func() { state, _ := ledgerPtr.GetState("chaincode1", "key1", true) Expect(state).To(Equal([]byte("value1"))) state, _ = ledgerPtr.GetState("chaincode2", "key2", true) Expect(state).To(Equal([]byte("value2"))) state, _ = ledgerPtr.GetState("chaincode3", "key3", true) Expect(state).To(Equal([]byte("value3")))
func (testWrapper *stateTestWrapper) fetchStateDeltaFromDB(blockNumber uint64) *statemgmt.StateDelta { delta := statemgmt.NewStateDelta() delta.Unmarshal(testDBWrapper.GetFromStateDeltaCF(testWrapper.t, encodeStateDeltaKey(blockNumber))) return delta }
func TestStateImpl_ComputeHash_DB_2(t *testing.T) { // number of buckets at each level 26,13,7,4,2,1 testHasher, stateImplTestWrapper, stateDelta := createFreshDBAndInitTestStateImplWithCustomHasher(t, 26, 2) testHasher.populate("chaincodeID1", "key1", 0) testHasher.populate("chaincodeID2", "key2", 1) testHasher.populate("chaincodeID3", "key3", 5) testHasher.populate("chaincodeID4", "key4", 9) testHasher.populate("chaincodeID5", "key5", 24) testHasher.populate("chaincodeID6", "key6", 25) stateDelta.Set("chaincodeID1", "key1", []byte("value1"), nil) stateDelta.Set("chaincodeID2", "key2", []byte("value2"), nil) stateDelta.Set("chaincodeID3", "key3", []byte("value3"), nil) stateDelta.Set("chaincodeID4", "key4", []byte("value4"), nil) stateDelta.Set("chaincodeID5", "key5", []byte("value5"), nil) stateDelta.Set("chaincodeID6", "key6", []byte("value6"), nil) stateImplTestWrapper.prepareWorkingSet(stateDelta) // Populate DB stateImplTestWrapper.persistChangesAndResetInMemoryChanges() //////////// Test - constrcuting a new state tree simulates starting state tree when db already has some data //////// stateImplTestWrapper.constructNewStateImpl() rootHash := stateImplTestWrapper.computeCryptoHash() /*************************** bucket-tree-structure *************** 1 1 1 1 1 1 2 1 1 1 1 1 6 3 2 1 1 1 10 5 3 2 1 1 25 13 7 4 2 1 26 13 7 4 2 1 *******************************************************************/ expectedHashBucket5_1 := expectedBucketHashForTest([]string{"chaincodeID1", "key1", "value1"}) expectedHashBucket5_2 := expectedBucketHashForTest([]string{"chaincodeID2", "key2", "value2"}) expectedHashBucket5_6 := expectedBucketHashForTest([]string{"chaincodeID3", "key3", "value3"}) expectedHashBucket5_10 := expectedBucketHashForTest([]string{"chaincodeID4", "key4", "value4"}) expectedHashBucket5_25 := expectedBucketHashForTest([]string{"chaincodeID5", "key5", "value5"}) expectedHashBucket5_26 := expectedBucketHashForTest([]string{"chaincodeID6", "key6", "value6"}) expectedHashBucket4_1 := testutil.ComputeCryptoHash(expectedHashBucket5_1, expectedHashBucket5_2) expectedHashBucket4_13 := testutil.ComputeCryptoHash(expectedHashBucket5_25, expectedHashBucket5_26) expectedHashBucket2_1 := testutil.ComputeCryptoHash(expectedHashBucket4_1, expectedHashBucket5_6) expectedHashBucket1_1 := testutil.ComputeCryptoHash(expectedHashBucket2_1, expectedHashBucket5_10) expectedHash := testutil.ComputeCryptoHash(expectedHashBucket1_1, expectedHashBucket4_13) testutil.AssertEquals(t, rootHash, expectedHash) ////////////// Test - Add a few more keys (include keys in the existing buckes and new buckets) ///////////////////// stateDelta = statemgmt.NewStateDelta() testHasher.populate("chaincodeID7", "key7", 1) testHasher.populate("chaincodeID8", "key8", 7) testHasher.populate("chaincodeID9", "key9", 9) testHasher.populate("chaincodeID10", "key10", 20) stateDelta.Set("chaincodeID7", "key7", []byte("value7"), nil) stateDelta.Set("chaincodeID8", "key8", []byte("value8"), nil) stateDelta.Set("chaincodeID9", "key9", []byte("value9"), nil) stateDelta.Set("chaincodeID10", "key10", []byte("value10"), nil) /*************************** bucket-tree-structure after adding keys *************** 1 1 1 1 1 1 2 1 1 1 1 1 6 3 2 1 1 1 8 4 2 1 1 1 10 5 3 2 1 1 21 11 6 3 2 1 25 13 7 4 2 1 26 13 7 4 2 1 ***********************************************************************************/ rootHash = stateImplTestWrapper.prepareWorkingSetAndComputeCryptoHash(stateDelta) expectedHashBucket5_2 = expectedBucketHashForTest( []string{"chaincodeID2", "key2", "value2"}, []string{"chaincodeID7", "key7", "value7"}, ) expectedHashBucket5_8 := expectedBucketHashForTest([]string{"chaincodeID8", "key8", "value8"}) expectedHashBucket5_10 = expectedBucketHashForTest([]string{"chaincodeID4", "key4", "value4"}, []string{"chaincodeID9", "key9", "value9"}) expectedHashBucket5_21 := expectedBucketHashForTest([]string{"chaincodeID10", "key10", "value10"}) expectedHashBucket4_1 = testutil.ComputeCryptoHash(expectedHashBucket5_1, expectedHashBucket5_2) expectedHashBucket3_2 := testutil.ComputeCryptoHash(expectedHashBucket5_6, expectedHashBucket5_8) expectedHashBucket2_1 = testutil.ComputeCryptoHash(expectedHashBucket4_1, expectedHashBucket3_2) expectedHashBucket1_1 = testutil.ComputeCryptoHash(expectedHashBucket2_1, expectedHashBucket5_10) expectedHashBucket1_2 := testutil.ComputeCryptoHash(expectedHashBucket5_21, expectedHashBucket4_13) expectedHash = testutil.ComputeCryptoHash(expectedHashBucket1_1, expectedHashBucket1_2) testutil.AssertEquals(t, rootHash, expectedHash) stateImplTestWrapper.persistChangesAndResetInMemoryChanges() ////////////// Test - overwrite an existing key ///////////////////// stateDelta = statemgmt.NewStateDelta() stateDelta.Set("chaincodeID7", "key7", []byte("value7_new"), nil) rootHash = stateImplTestWrapper.prepareWorkingSetAndComputeCryptoHash(stateDelta) expectedHashBucket5_2 = expectedBucketHashForTest( []string{"chaincodeID2", "key2", "value2"}, []string{"chaincodeID7", "key7", "value7_new"}, ) expectedHashBucket4_1 = testutil.ComputeCryptoHash(expectedHashBucket5_1, expectedHashBucket5_2) expectedHashBucket2_1 = testutil.ComputeCryptoHash(expectedHashBucket4_1, expectedHashBucket3_2) expectedHashBucket1_1 = testutil.ComputeCryptoHash(expectedHashBucket2_1, expectedHashBucket5_10) expectedHash = testutil.ComputeCryptoHash(expectedHashBucket1_1, expectedHashBucket1_2) testutil.AssertEquals(t, rootHash, expectedHash) stateImplTestWrapper.persistChangesAndResetInMemoryChanges() testutil.AssertEquals(t, stateImplTestWrapper.get("chaincodeID7", "key7"), []byte("value7_new")) // ////////////// Test - delete an existing key ///////////////////// stateDelta = statemgmt.NewStateDelta() stateDelta.Delete("chaincodeID2", "key2", nil) rootHash = stateImplTestWrapper.prepareWorkingSetAndComputeCryptoHash(stateDelta) expectedHashBucket5_2 = expectedBucketHashForTest([]string{"chaincodeID7", "key7", "value7_new"}) expectedHashBucket4_1 = testutil.ComputeCryptoHash(expectedHashBucket5_1, expectedHashBucket5_2) expectedHashBucket2_1 = testutil.ComputeCryptoHash(expectedHashBucket4_1, expectedHashBucket3_2) expectedHashBucket1_1 = testutil.ComputeCryptoHash(expectedHashBucket2_1, expectedHashBucket5_10) expectedHash = testutil.ComputeCryptoHash(expectedHashBucket1_1, expectedHashBucket1_2) testutil.AssertEquals(t, rootHash, expectedHash) stateImplTestWrapper.persistChangesAndResetInMemoryChanges() testutil.AssertNil(t, stateImplTestWrapper.get("chaincodeID2", "key2")) }
func TestStateImpl_ComputeHash_AllInMemory_NoContents(t *testing.T) { testDBWrapper.CreateFreshDB(t) stateImplTestWrapper := newStateImplTestWrapper(t) hash := stateImplTestWrapper.prepareWorkingSetAndComputeCryptoHash(statemgmt.NewStateDelta()) testutil.AssertEquals(t, hash, nil) }
func TestLedgerSetRawState(t *testing.T) { ledgerTestWrapper := createFreshDBAndTestLedgerWrapper(t) ledger := ledgerTestWrapper.ledger ledger.BeginTxBatch(1) ledger.TxBegin("txUuid1") ledger.SetState("chaincode1", "key1", []byte("value1")) ledger.SetState("chaincode2", "key2", []byte("value2")) ledger.SetState("chaincode3", "key3", []byte("value3")) ledger.TxFinished("txUuid1", true) transaction, _ := buildTestTx(t) ledger.CommitTxBatch(1, []*protos.Transaction{transaction}, nil, []byte("proof")) // Ensure values are in the DB val := ledgerTestWrapper.GetState("chaincode1", "key1", true) if bytes.Compare(val, []byte("value1")) != 0 { t.Fatalf("Expected initial chaincode1 key1 to be %s, but got %s", []byte("value1"), val) } val = ledgerTestWrapper.GetState("chaincode2", "key2", true) if bytes.Compare(val, []byte("value2")) != 0 { t.Fatalf("Expected initial chaincode1 key2 to be %s, but got %s", []byte("value2"), val) } val = ledgerTestWrapper.GetState("chaincode3", "key3", true) if bytes.Compare(val, []byte("value3")) != 0 { t.Fatalf("Expected initial chaincode1 key3 to be %s, but got %s", []byte("value3"), val) } hash1, hash1Err := ledger.GetTempStateHash() if hash1Err != nil { t.Fatalf("Error getting hash1 %s", hash1Err) } snapshot, snapshotError := ledger.GetStateSnapshot() if snapshotError != nil { t.Fatalf("Error fetching snapshot %s", snapshotError) } defer snapshot.Release() // Delete keys ledger.BeginTxBatch(2) ledger.TxBegin("txUuid2") ledger.DeleteState("chaincode1", "key1") ledger.DeleteState("chaincode2", "key2") ledger.DeleteState("chaincode3", "key3") ledger.TxFinished("txUuid2", true) transaction, _ = buildTestTx(t) ledger.CommitTxBatch(2, []*protos.Transaction{transaction}, nil, []byte("proof")) // ensure keys are deleted val = ledgerTestWrapper.GetState("chaincode1", "key1", true) if val != nil { t.Fatalf("Expected chaincode1 key1 to be nil, but got %s", val) } val = ledgerTestWrapper.GetState("chaincode2", "key2", true) if val != nil { t.Fatalf("Expected chaincode2 key2 to be nil, but got %s", val) } val = ledgerTestWrapper.GetState("chaincode3", "key3", true) if val != nil { t.Fatalf("Expected chaincode3 key3 to be nil, but got %s", val) } hash2, hash2Err := ledger.GetTempStateHash() if hash2Err != nil { t.Fatalf("Error getting hash2 %s", hash2Err) } if bytes.Compare(hash1, hash2) == 0 { t.Fatalf("Expected hashes to not match, but they both equal %s", hash1) } // put key/values from the snapshot back in the DB //var keys, values [][]byte delta := statemgmt.NewStateDelta() for i := 0; snapshot.Next(); i++ { k, v := snapshot.GetRawKeyValue() cID, keyID := statemgmt.DecodeCompositeKey(k) delta.Set(cID, keyID, v, nil) } ledgerTestWrapper.ApplyStateDelta(1, delta) ledgerTestWrapper.CommitStateDelta(1) // Ensure values are back in the DB val = ledgerTestWrapper.GetState("chaincode1", "key1", true) if bytes.Compare(val, []byte("value1")) != 0 { t.Fatalf("Expected chaincode1 key1 to be %s, but got %s", []byte("value1"), val) } val = ledgerTestWrapper.GetState("chaincode2", "key2", true) if bytes.Compare(val, []byte("value2")) != 0 { t.Fatalf("Expected chaincode1 key2 to be %s, but got %s", []byte("value2"), val) } val = ledgerTestWrapper.GetState("chaincode3", "key3", true) if bytes.Compare(val, []byte("value3")) != 0 { t.Fatalf("Expected chaincode1 key3 to be %s, but got %s", []byte("value3"), val) } hash3, hash3Err := ledger.GetTempStateHash() if hash3Err != nil { t.Fatalf("Error getting hash3 %s", hash3Err) } if bytes.Compare(hash1, hash3) != 0 { t.Fatalf("Expected hashes to be equal, but they are %s and %s", hash1, hash3) } }
// ClearInMemoryChanges remove from memory all the changes to state func (state *State) ClearInMemoryChanges(changesPersisted bool) { state.stateDelta = statemgmt.NewStateDelta() state.txStateDeltaHash = make(map[string][]byte) state.stateImpl.ClearWorkingSet(changesPersisted) }
func TestStateTrie_ComputeHash_WithDB_Staggered_Keys(t *testing.T) { testDBWrapper.CleanDB(t) stateTrie := NewStateTrie() stateTrieTestWrapper := &stateTrieTestWrapper{stateTrie, t} ///////////////////////////////////////////////////////// // Test1 - Add a few staggered keys ///////////////////////////////////////////////////////// stateDelta := statemgmt.NewStateDelta() stateDelta.Set("ID", "key1", []byte("value_key1"), nil) stateDelta.Set("ID", "key", []byte("value_key"), nil) stateDelta.Set("ID", "k", []byte("value_k"), nil) expectedHashKey1 := expectedCryptoHashForTest(newTrieKey("ID", "key1"), []byte("value_key1")) expectedHashKey := expectedCryptoHashForTest(newTrieKey("ID", "key"), []byte("value_key"), expectedHashKey1) expectedHashK := expectedCryptoHashForTest(newTrieKey("ID", "k"), []byte("value_k"), expectedHashKey) rootHash1 := stateTrieTestWrapper.PrepareWorkingSetAndComputeCryptoHash(stateDelta) testutil.AssertEquals(t, rootHash1, expectedHashK) stateTrieTestWrapper.PersistChangesAndResetInMemoryChanges() ///////////////////////////////////////////////////////// // Test2 - Add a new key in path of existing staggered keys ///////////////////////////////////////////////////////// t.Logf("- Add a new key in path of existing staggered keys -") stateDelta = statemgmt.NewStateDelta() stateDelta.Set("ID", "ke", []byte("value_ke"), nil) expectedHashKe := expectedCryptoHashForTest(newTrieKey("ID", "ke"), []byte("value_ke"), expectedHashKey) expectedHashK = expectedCryptoHashForTest(newTrieKey("ID", "k"), []byte("value_k"), expectedHashKe) rootHash2 := stateTrieTestWrapper.PrepareWorkingSetAndComputeCryptoHash(stateDelta) testutil.AssertEquals(t, rootHash2, expectedHashK) stateTrieTestWrapper.PersistChangesAndResetInMemoryChanges() ///////////////////////////////////////////////////////// // Test3 - Change value of one of the existing keys ///////////////////////////////////////////////////////// stateDelta = statemgmt.NewStateDelta() stateDelta.Set("ID", "ke", []byte("value_ke_new"), nil) expectedHashKe = expectedCryptoHashForTest(newTrieKey("ID", "ke"), []byte("value_ke_new"), expectedHashKey) expectedHashK = expectedCryptoHashForTest(newTrieKey("ID", "k"), []byte("value_k"), expectedHashKe) rootHash3 := stateTrieTestWrapper.PrepareWorkingSetAndComputeCryptoHash(stateDelta) testutil.AssertEquals(t, rootHash3, expectedHashK) stateTrieTestWrapper.PersistChangesAndResetInMemoryChanges() ///////////////////////////////////////////////////////// // Test4 - delete one of the existing keys ///////////////////////////////////////////////////////// stateDelta = statemgmt.NewStateDelta() stateDelta.Delete("ID", "ke", nil) expectedHashK = expectedCryptoHashForTest(newTrieKey("ID", "k"), []byte("value_k"), expectedHashKey) rootHash4 := stateTrieTestWrapper.PrepareWorkingSetAndComputeCryptoHash(stateDelta) testutil.AssertEquals(t, rootHash4, expectedHashK) stateTrieTestWrapper.PersistChangesAndResetInMemoryChanges() // Delete should not remove the key from db because, this key has children testutil.AssertNotNil(t, testDBWrapper.GetFromStateCF(t, newTrieKey("ID", "ke").getEncodedBytes())) testutil.AssertEquals(t, rootHash1, rootHash4) ////////////////////////////////////////////////////////////// // Test4 - Add one more key as a sibling of an intermediate node ////////////////////////////////////////////////////////////// stateDelta = statemgmt.NewStateDelta() stateDelta.Set("ID", "kez", []byte("value_kez"), nil) expectedHashKez := expectedCryptoHashForTest(newTrieKey("ID", "kez"), []byte("value_kez")) expectedHashKe = expectedCryptoHashForTest(nil, nil, expectedHashKey, expectedHashKez) expectedHashK = expectedCryptoHashForTest(newTrieKey("ID", "k"), []byte("value_k"), expectedHashKe) rootHash5 := stateTrieTestWrapper.PrepareWorkingSetAndComputeCryptoHash(stateDelta) testutil.AssertEquals(t, rootHash5, expectedHashK) }
func TestStateTrie_ComputeHash_WithDB_Spread_Keys(t *testing.T) { testDBWrapper.CleanDB(t) stateTrie := NewStateTrie() stateTrieTestWrapper := &stateTrieTestWrapper{stateTrie, t} // Add a few keys and write to DB stateDelta := statemgmt.NewStateDelta() stateDelta.Set("chaincodeID1", "key1", []byte("value1"), nil) stateDelta.Set("chaincodeID1", "key2", []byte("value2"), nil) stateDelta.Set("chaincodeID2", "key3", []byte("value3"), nil) stateDelta.Set("chaincodeID2", "key4", []byte("value4"), nil) stateTrie.PrepareWorkingSet(stateDelta) stateTrieTestWrapper.PersistChangesAndResetInMemoryChanges() ///////////////////////////////////////////////////////// // Test1 - Add a non-existing key ///////////////////////////////////////////////////////// stateDelta = statemgmt.NewStateDelta() stateDelta.Set("chaincodeID3", "key5", []byte("value5"), nil) rootHash1 := stateTrieTestWrapper.PrepareWorkingSetAndComputeCryptoHash(stateDelta) expectedHash1 := expectedCryptoHashForTest(newTrieKey("chaincodeID1", "key1"), []byte("value1")) expectedHash2 := expectedCryptoHashForTest(newTrieKey("chaincodeID1", "key2"), []byte("value2")) expectedHash3 := expectedCryptoHashForTest(newTrieKey("chaincodeID2", "key3"), []byte("value3")) expectedHash4 := expectedCryptoHashForTest(newTrieKey("chaincodeID2", "key4"), []byte("value4")) expectedHash1Hash2 := expectedCryptoHashForTest(nil, nil, expectedHash1, expectedHash2) expectedHash3Hash4 := expectedCryptoHashForTest(nil, nil, expectedHash3, expectedHash4) expectedHash5 := expectedCryptoHashForTest(newTrieKey("chaincodeID3", "key5"), []byte("value5")) expectedRootHash1 := expectedCryptoHashForTest(nil, nil, expectedHash1Hash2, expectedHash3Hash4, expectedHash5) testutil.AssertEquals(t, rootHash1, expectedRootHash1) stateTrieTestWrapper.PersistChangesAndResetInMemoryChanges() ///////////////////////////////////////////////////////// // Test2 - Change value of an existing key ///////////////////////////////////////////////////////// stateDelta = statemgmt.NewStateDelta() stateDelta.Set("chaincodeID2", "key4", []byte("value4-new"), nil) rootHash2 := stateTrieTestWrapper.PrepareWorkingSetAndComputeCryptoHash(stateDelta) expectedHash4 = expectedCryptoHashForTest(newTrieKey("chaincodeID2", "key4"), []byte("value4-new")) expectedHash3Hash4 = expectedCryptoHashForTest(nil, nil, expectedHash3, expectedHash4) expectedRootHash2 := expectedCryptoHashForTest(nil, nil, expectedHash1Hash2, expectedHash3Hash4, expectedHash5) testutil.AssertEquals(t, rootHash2, expectedRootHash2) stateTrieTestWrapper.PersistChangesAndResetInMemoryChanges() ///////////////////////////////////////////////////////// // Test3 - Change value of another existing key ///////////////////////////////////////////////////////// stateDelta = statemgmt.NewStateDelta() stateDelta.Set("chaincodeID1", "key1", []byte("value1-new"), nil) rootHash3 := stateTrieTestWrapper.PrepareWorkingSetAndComputeCryptoHash(stateDelta) expectedHash1 = expectedCryptoHashForTest(newTrieKey("chaincodeID1", "key1"), []byte("value1-new")) expectedHash1Hash2 = expectedCryptoHashForTest(nil, nil, expectedHash1, expectedHash2) expectedRootHash3 := expectedCryptoHashForTest(nil, nil, expectedHash1Hash2, expectedHash3Hash4, expectedHash5) testutil.AssertEquals(t, rootHash3, expectedRootHash3) stateTrieTestWrapper.PersistChangesAndResetInMemoryChanges() ///////////////////////////////////////////////////////// // Test4 - Delete an existing existing key ///////////////////////////////////////////////////////// t.Logf("-- Delete an existing key ---") stateDelta = statemgmt.NewStateDelta() stateDelta.Delete("chaincodeID3", "key5", nil) rootHash4 := stateTrieTestWrapper.PrepareWorkingSetAndComputeCryptoHash(stateDelta) expectedRootHash4 := expectedCryptoHashForTest(nil, nil, expectedHash1Hash2, expectedHash3Hash4) testutil.AssertEquals(t, rootHash4, expectedRootHash4) stateTrieTestWrapper.PersistChangesAndResetInMemoryChanges() // Delete should remove the key from db because, this key has no value and no children testutil.AssertNil(t, testDBWrapper.GetFromStateCF(t, newTrieKey("chaincodeID3", "key5").getEncodedBytes())) ///////////////////////////////////////////////////////// // Test5 - Delete another existing existing key ///////////////////////////////////////////////////////// stateDelta = statemgmt.NewStateDelta() stateDelta.Delete("chaincodeID2", "key4", nil) rootHash5 := stateTrieTestWrapper.PrepareWorkingSetAndComputeCryptoHash(stateDelta) expectedRootHash5 := expectedCryptoHashForTest(nil, nil, expectedHash1Hash2, expectedHash3) testutil.AssertEquals(t, rootHash5, expectedRootHash5) stateTrieTestWrapper.PersistChangesAndResetInMemoryChanges() testutil.AssertNil(t, testDBWrapper.GetFromStateCF(t, newTrieKey("chaincodeID2", "key4").getEncodedBytes())) }
func TestRangeScanIterator(t *testing.T) { testDBWrapper.CleanDB(t) stateTrieTestWrapper := newStateTrieTestWrapper(t) stateTrie := stateTrieTestWrapper.stateTrie stateDelta := statemgmt.NewStateDelta() // insert keys stateDelta.Set("chaincodeID1", "key1", []byte("value1"), nil) stateDelta.Set("chaincodeID2", "key1", []byte("value1"), nil) stateDelta.Set("chaincodeID2", "key2", []byte("value2"), nil) stateDelta.Set("chaincodeID2", "key3", []byte("value3"), nil) stateDelta.Set("chaincodeID2", "key4", []byte("value4"), nil) stateDelta.Set("chaincodeID2", "key5", []byte("value5"), nil) stateDelta.Set("chaincodeID2", "key6", []byte("value6"), nil) stateDelta.Set("chaincodeID2", "key7", []byte("value7"), nil) stateDelta.Set("chaincodeID3", "key1", []byte("value1"), nil) stateDelta.Set("chaincodeID4", "key1", []byte("value1"), nil) stateDelta.Set("chaincodeID4", "key2", []byte("value2"), nil) stateDelta.Set("chaincodeID4", "key3", []byte("value3"), nil) stateDelta.Set("chaincodeID4", "key4", []byte("value4"), nil) stateDelta.Set("chaincodeID4", "key5", []byte("value5"), nil) stateDelta.Set("chaincodeID4", "key6", []byte("value6"), nil) stateDelta.Set("chaincodeID4", "key7", []byte("value7"), nil) stateDelta.Set("chaincodeID5", "key1", []byte("value5"), nil) stateDelta.Set("chaincodeID6", "key1", []byte("value6"), nil) stateTrie.PrepareWorkingSet(stateDelta) stateTrieTestWrapper.PersistChangesAndResetInMemoryChanges() // test range scan for chaincodeID2 rangeScanItr, _ := stateTrie.GetRangeScanIterator("chaincodeID2", "key2", "key5") var results = make(map[string][]byte) for rangeScanItr.Next() { key, value := rangeScanItr.GetKeyValue() results[key] = value } t.Logf("Results = %s", results) testutil.AssertEquals(t, len(results), 4) testutil.AssertEquals(t, results["key2"], []byte("value2")) testutil.AssertEquals(t, results["key3"], []byte("value3")) testutil.AssertEquals(t, results["key4"], []byte("value4")) testutil.AssertEquals(t, results["key5"], []byte("value5")) rangeScanItr.Close() // test range scan for chaincodeID4 rangeScanItr, _ = stateTrie.GetRangeScanIterator("chaincodeID2", "key3", "key6") results = make(map[string][]byte) for rangeScanItr.Next() { key, value := rangeScanItr.GetKeyValue() results[key] = value } t.Logf("Results = %s", results) testutil.AssertEquals(t, len(results), 4) testutil.AssertEquals(t, results["key3"], []byte("value3")) testutil.AssertEquals(t, results["key4"], []byte("value4")) testutil.AssertEquals(t, results["key5"], []byte("value5")) testutil.AssertEquals(t, results["key6"], []byte("value6")) rangeScanItr.Close() // test range scan for chaincodeID2 starting from first key rangeScanItr, _ = stateTrie.GetRangeScanIterator("chaincodeID2", "", "key5") results = make(map[string][]byte) for rangeScanItr.Next() { key, value := rangeScanItr.GetKeyValue() results[key] = value } t.Logf("Results = %s", results) testutil.AssertEquals(t, len(results), 5) testutil.AssertEquals(t, results["key1"], []byte("value1")) testutil.AssertEquals(t, results["key2"], []byte("value2")) testutil.AssertEquals(t, results["key3"], []byte("value3")) testutil.AssertEquals(t, results["key4"], []byte("value4")) testutil.AssertEquals(t, results["key5"], []byte("value5")) rangeScanItr.Close() // test range scan for all the keys in chaincodeID2 starting from first key rangeScanItr, _ = stateTrie.GetRangeScanIterator("chaincodeID2", "", "") results = make(map[string][]byte) for rangeScanItr.Next() { key, value := rangeScanItr.GetKeyValue() results[key] = value } t.Logf("Results = %s", results) testutil.AssertEquals(t, len(results), 7) testutil.AssertEquals(t, results["key1"], []byte("value1")) testutil.AssertEquals(t, results["key2"], []byte("value2")) testutil.AssertEquals(t, results["key3"], []byte("value3")) testutil.AssertEquals(t, results["key4"], []byte("value4")) testutil.AssertEquals(t, results["key5"], []byte("value5")) testutil.AssertEquals(t, results["key6"], []byte("value6")) testutil.AssertEquals(t, results["key7"], []byte("value7")) rangeScanItr.Close() }
func TestStateImpl_ComputeHash_DB_1(t *testing.T) { // number of buckets at each level 26,9,3,1 testHasher, stateImplTestWrapper, stateDelta := createFreshDBAndInitTestStateImplWithCustomHasher(t, 26, 3) // populate hash fucntion such that // all keys belong to a single bucket so as to test overwrite/delete scenario testHasher.populate("chaincodeID1", "key1", 3) testHasher.populate("chaincodeID2", "key2", 3) testHasher.populate("chaincodeID3", "key3", 3) testHasher.populate("chaincodeID4", "key4", 3) testHasher.populate("chaincodeID5", "key5", 3) testHasher.populate("chaincodeID6", "key6", 3) testHasher.populate("chaincodeID7", "key7", 3) stateDelta.Set("chaincodeID2", "key2", []byte("value2"), nil) stateDelta.Set("chaincodeID3", "key3", []byte("value3"), nil) stateDelta.Set("chaincodeID5", "key5", []byte("value5"), nil) stateDelta.Set("chaincodeID6", "key6", []byte("value6"), nil) rootHash := stateImplTestWrapper.prepareWorkingSetAndComputeCryptoHash(stateDelta) stateImplTestWrapper.persistChangesAndResetInMemoryChanges() expectedHash1 := expectedBucketHashForTest( []string{"chaincodeID2", "key2", "value2"}, []string{"chaincodeID3", "key3", "value3"}, []string{"chaincodeID5", "key5", "value5"}, []string{"chaincodeID6", "key6", "value6"}, ) testutil.AssertEquals(t, rootHash, expectedHash1) // modify boundary keys and a middle key stateDelta = statemgmt.NewStateDelta() stateDelta.Set("chaincodeID2", "key2", []byte("value2_new"), nil) stateDelta.Set("chaincodeID3", "key3", []byte("value3_new"), nil) stateDelta.Set("chaincodeID6", "key6", []byte("value6_new"), nil) rootHash = stateImplTestWrapper.prepareWorkingSetAndComputeCryptoHash(stateDelta) stateImplTestWrapper.persistChangesAndResetInMemoryChanges() expectedHash2 := expectedBucketHashForTest( []string{"chaincodeID2", "key2", "value2_new"}, []string{"chaincodeID3", "key3", "value3_new"}, []string{"chaincodeID5", "key5", "value5"}, []string{"chaincodeID6", "key6", "value6_new"}, ) testutil.AssertEquals(t, rootHash, expectedHash2) testutil.AssertEquals(t, stateImplTestWrapper.get("chaincodeID2", "key2"), []byte("value2_new")) testutil.AssertEquals(t, stateImplTestWrapper.get("chaincodeID3", "key3"), []byte("value3_new")) testutil.AssertEquals(t, stateImplTestWrapper.get("chaincodeID6", "key6"), []byte("value6_new")) // insert keys at boundary and in the middle stateDelta = statemgmt.NewStateDelta() stateDelta.Set("chaincodeID1", "key1", []byte("value1"), nil) stateDelta.Set("chaincodeID4", "key4", []byte("value4"), nil) stateDelta.Set("chaincodeID7", "key7", []byte("value7"), nil) rootHash = stateImplTestWrapper.prepareWorkingSetAndComputeCryptoHash(stateDelta) stateImplTestWrapper.persistChangesAndResetInMemoryChanges() expectedHash3 := expectedBucketHashForTest( []string{"chaincodeID1", "key1", "value1"}, []string{"chaincodeID2", "key2", "value2_new"}, []string{"chaincodeID3", "key3", "value3_new"}, []string{"chaincodeID4", "key4", "value4"}, []string{"chaincodeID5", "key5", "value5"}, []string{"chaincodeID6", "key6", "value6_new"}, []string{"chaincodeID7", "key7", "value7"}, ) testutil.AssertEquals(t, rootHash, expectedHash3) testutil.AssertEquals(t, stateImplTestWrapper.get("chaincodeID1", "key1"), []byte("value1")) testutil.AssertEquals(t, stateImplTestWrapper.get("chaincodeID4", "key4"), []byte("value4")) testutil.AssertEquals(t, stateImplTestWrapper.get("chaincodeID7", "key7"), []byte("value7")) // delete keys at a boundary and in the middle stateDelta = statemgmt.NewStateDelta() stateDelta.Delete("chaincodeID1", "key1", nil) stateDelta.Delete("chaincodeID4", "key4", nil) stateDelta.Delete("chaincodeID7", "key7", nil) rootHash = stateImplTestWrapper.prepareWorkingSetAndComputeCryptoHash(stateDelta) stateImplTestWrapper.persistChangesAndResetInMemoryChanges() testutil.AssertEquals(t, rootHash, expectedHash2) testutil.AssertNil(t, stateImplTestWrapper.get("chaincodeID1", "key1")) testutil.AssertNil(t, stateImplTestWrapper.get("chaincodeID4", "key4")) testutil.AssertNil(t, stateImplTestWrapper.get("chaincodeID7", "key7")) }