github.com/true-sqn/fabric@v2.1.1+incompatible/core/ledger/kvledger/txmgmt/privacyenabledstate/db.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 "fmt" 11 12 "github.com/hyperledger/fabric/core/ledger/cceventmgmt" 13 "github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt/statedb" 14 "github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt/version" 15 ) 16 17 // DBProvider provides handle to a PvtVersionedDB 18 type DBProvider interface { 19 // GetDBHandle returns a handle to a PvtVersionedDB 20 GetDBHandle(id string) (DB, error) 21 // Close closes all the PvtVersionedDB instances and releases any resources held by VersionedDBProvider 22 Close() 23 } 24 25 // DB extends VersionedDB interface. This interface provides additional functions for managing private data state 26 type DB interface { 27 statedb.VersionedDB 28 IsBulkOptimizable() bool 29 LoadCommittedVersionsOfPubAndHashedKeys(pubKeys []*statedb.CompositeKey, hashedKeys []*HashedCompositeKey) error 30 GetCachedKeyHashVersion(namespace, collection string, keyHash []byte) (*version.Height, bool) 31 ClearCachedVersions() 32 GetChaincodeEventListener() cceventmgmt.ChaincodeLifecycleEventListener 33 GetPrivateData(namespace, collection, key string) (*statedb.VersionedValue, error) 34 GetPrivateDataHash(namespace, collection, key string) (*statedb.VersionedValue, error) 35 GetValueHash(namespace, collection string, keyHash []byte) (*statedb.VersionedValue, error) 36 GetKeyHashVersion(namespace, collection string, keyHash []byte) (*version.Height, error) 37 GetPrivateDataMultipleKeys(namespace, collection string, keys []string) ([]*statedb.VersionedValue, error) 38 GetPrivateDataRangeScanIterator(namespace, collection, startKey, endKey string) (statedb.ResultsIterator, error) 39 GetStateMetadata(namespace, key string) ([]byte, error) 40 GetPrivateDataMetadataByHash(namespace, collection string, keyHash []byte) ([]byte, error) 41 ExecuteQueryOnPrivateData(namespace, collection, query string) (statedb.ResultsIterator, error) 42 ApplyPrivacyAwareUpdates(updates *UpdateBatch, height *version.Height) error 43 } 44 45 // PvtdataCompositeKey encloses Namespace, CollectionName and Key components 46 type PvtdataCompositeKey struct { 47 Namespace string 48 CollectionName string 49 Key string 50 } 51 52 // HashedCompositeKey encloses Namespace, CollectionName and KeyHash components 53 type HashedCompositeKey struct { 54 Namespace string 55 CollectionName string 56 KeyHash string 57 } 58 59 // PvtKVWrite encloses Key, IsDelete, Value, and Version components 60 type PvtKVWrite struct { 61 Key string 62 IsDelete bool 63 Value []byte 64 Version *version.Height 65 } 66 67 // UpdateBatch encapsulates the updates to Public, Private, and Hashed data. 68 // This is expected to contain a consistent set of updates 69 type UpdateBatch struct { 70 PubUpdates *PubUpdateBatch 71 HashUpdates *HashedUpdateBatch 72 PvtUpdates *PvtUpdateBatch 73 } 74 75 // PubUpdateBatch contains update for the public data 76 type PubUpdateBatch struct { 77 *statedb.UpdateBatch 78 } 79 80 // HashedUpdateBatch contains updates for the hashes of the private data 81 type HashedUpdateBatch struct { 82 UpdateMap 83 } 84 85 // PvtUpdateBatch contains updates for the private data 86 type PvtUpdateBatch struct { 87 UpdateMap 88 } 89 90 // UpdateMap maintains entries of tuple <Namespace, UpdatesForNamespace> 91 type UpdateMap map[string]nsBatch 92 93 // nsBatch contains updates related to one namespace 94 type nsBatch struct { 95 *statedb.UpdateBatch 96 } 97 98 // NewUpdateBatch creates and empty UpdateBatch 99 func NewUpdateBatch() *UpdateBatch { 100 return &UpdateBatch{NewPubUpdateBatch(), NewHashedUpdateBatch(), NewPvtUpdateBatch()} 101 } 102 103 // NewPubUpdateBatch creates an empty PubUpdateBatch 104 func NewPubUpdateBatch() *PubUpdateBatch { 105 return &PubUpdateBatch{statedb.NewUpdateBatch()} 106 } 107 108 // NewHashedUpdateBatch creates an empty HashedUpdateBatch 109 func NewHashedUpdateBatch() *HashedUpdateBatch { 110 return &HashedUpdateBatch{make(map[string]nsBatch)} 111 } 112 113 // NewPvtUpdateBatch creates an empty PvtUpdateBatch 114 func NewPvtUpdateBatch() *PvtUpdateBatch { 115 return &PvtUpdateBatch{make(map[string]nsBatch)} 116 } 117 118 // IsEmpty returns true if there exists any updates 119 func (b UpdateMap) IsEmpty() bool { 120 return len(b) == 0 121 } 122 123 // Put sets the value in the batch for a given combination of namespace and collection name 124 func (b UpdateMap) Put(ns, coll, key string, value []byte, version *version.Height) { 125 b.PutValAndMetadata(ns, coll, key, value, nil, version) 126 } 127 128 // PutValAndMetadata adds a key with value and metadata 129 func (b UpdateMap) PutValAndMetadata(ns, coll, key string, value []byte, metadata []byte, version *version.Height) { 130 b.getOrCreateNsBatch(ns).PutValAndMetadata(coll, key, value, metadata, version) 131 } 132 133 // Delete adds a delete marker in the batch for a given combination of namespace and collection name 134 func (b UpdateMap) Delete(ns, coll, key string, version *version.Height) { 135 b.getOrCreateNsBatch(ns).Delete(coll, key, version) 136 } 137 138 // Get retrieves the value from the batch for a given combination of namespace and collection name 139 func (b UpdateMap) Get(ns, coll, key string) *statedb.VersionedValue { 140 nsPvtBatch, ok := b[ns] 141 if !ok { 142 return nil 143 } 144 return nsPvtBatch.Get(coll, key) 145 } 146 147 // Contains returns true if the given <ns,coll,key> tuple is present in the batch 148 func (b UpdateMap) Contains(ns, coll, key string) bool { 149 nsBatch, ok := b[ns] 150 if !ok { 151 return false 152 } 153 return nsBatch.Exists(coll, key) 154 } 155 156 func (nsb nsBatch) GetCollectionNames() []string { 157 return nsb.GetUpdatedNamespaces() 158 } 159 160 func (nsb nsBatch) getCollectionUpdates(collName string) map[string]*statedb.VersionedValue { 161 return nsb.GetUpdates(collName) 162 } 163 164 func (b UpdateMap) getUpdatedNamespaces() []string { 165 namespaces := []string{} 166 for ns := range b { 167 namespaces = append(namespaces, ns) 168 } 169 return namespaces 170 } 171 172 func (b UpdateMap) getOrCreateNsBatch(ns string) nsBatch { 173 batch, ok := b[ns] 174 if !ok { 175 batch = nsBatch{statedb.NewUpdateBatch()} 176 b[ns] = batch 177 } 178 return batch 179 } 180 181 // Contains returns true if the given <ns,coll,keyHash> tuple is present in the batch 182 func (h HashedUpdateBatch) Contains(ns, coll string, keyHash []byte) bool { 183 return h.UpdateMap.Contains(ns, coll, string(keyHash)) 184 } 185 186 // Put overrides the function in UpdateMap for allowing the key to be a []byte instead of a string 187 func (h HashedUpdateBatch) Put(ns, coll string, key []byte, value []byte, version *version.Height) { 188 h.PutValHashAndMetadata(ns, coll, key, value, nil, version) 189 } 190 191 // PutValHashAndMetadata adds a key with value and metadata 192 // TODO introducing a new function to limit the refactoring. Later in a separate CR, the 'Put' function above should be removed 193 func (h HashedUpdateBatch) PutValHashAndMetadata(ns, coll string, key []byte, value []byte, metadata []byte, version *version.Height) { 194 h.UpdateMap.PutValAndMetadata(ns, coll, string(key), value, metadata, version) 195 } 196 197 // Delete overrides the function in UpdateMap for allowing the key to be a []byte instead of a string 198 func (h HashedUpdateBatch) Delete(ns, coll string, key []byte, version *version.Height) { 199 h.UpdateMap.Delete(ns, coll, string(key), version) 200 } 201 202 // ToCompositeKeyMap rearranges the update batch data in the form of a single map 203 func (h HashedUpdateBatch) ToCompositeKeyMap() map[HashedCompositeKey]*statedb.VersionedValue { 204 m := make(map[HashedCompositeKey]*statedb.VersionedValue) 205 for ns, nsBatch := range h.UpdateMap { 206 for _, coll := range nsBatch.GetCollectionNames() { 207 for key, vv := range nsBatch.GetUpdates(coll) { 208 m[HashedCompositeKey{ns, coll, key}] = vv 209 } 210 } 211 } 212 return m 213 } 214 215 // PvtdataCompositeKeyMap is a map of PvtdataCompositeKey to VersionedValue 216 type PvtdataCompositeKeyMap map[PvtdataCompositeKey]*statedb.VersionedValue 217 218 // ToCompositeKeyMap rearranges the update batch data in the form of a single map 219 func (p PvtUpdateBatch) ToCompositeKeyMap() PvtdataCompositeKeyMap { 220 m := make(PvtdataCompositeKeyMap) 221 for ns, nsBatch := range p.UpdateMap { 222 for _, coll := range nsBatch.GetCollectionNames() { 223 for key, vv := range nsBatch.GetUpdates(coll) { 224 m[PvtdataCompositeKey{ns, coll, key}] = vv 225 } 226 } 227 } 228 return m 229 } 230 231 // String returns a print friendly form of HashedCompositeKey 232 func (hck *HashedCompositeKey) String() string { 233 return fmt.Sprintf("ns=%s, collection=%s, keyHash=%x", hck.Namespace, hck.CollectionName, hck.KeyHash) 234 }