github.com/ewagmig/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  }