github.com/renegr87/renegr87@v2.1.1+incompatible/core/ledger/kvledger/txmgmt/rwsetutil/rwset_proto_util.go (about)

     1  /*
     2  Copyright IBM Corp. 2016 All Rights Reserved.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8  		 http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package rwsetutil
    18  
    19  import (
    20  	"github.com/golang/protobuf/proto"
    21  	"github.com/hyperledger/fabric-protos-go/ledger/rwset"
    22  	"github.com/hyperledger/fabric-protos-go/ledger/rwset/kvrwset"
    23  	"github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt/version"
    24  	"github.com/hyperledger/fabric/core/ledger/util"
    25  )
    26  
    27  /////////////////////////////////////////////////////////////////
    28  // Messages related to PUBLIC read-write set
    29  /////////////////////////////////////////////////////////////////
    30  
    31  // TxRwSet acts as a proxy of 'rwset.TxReadWriteSet' proto message and helps constructing Read-write set specifically for KV data model
    32  type TxRwSet struct {
    33  	NsRwSets []*NsRwSet
    34  }
    35  
    36  // NsRwSet encapsulates 'kvrwset.KVRWSet' proto message for a specific name space (chaincode)
    37  type NsRwSet struct {
    38  	NameSpace        string
    39  	KvRwSet          *kvrwset.KVRWSet
    40  	CollHashedRwSets []*CollHashedRwSet
    41  }
    42  
    43  // CollHashedRwSet encapsulates 'kvrwset.HashedRWSet' proto message for a specific collection
    44  type CollHashedRwSet struct {
    45  	CollectionName string
    46  	HashedRwSet    *kvrwset.HashedRWSet
    47  	PvtRwSetHash   []byte
    48  }
    49  
    50  // GetPvtDataHash returns the PvtRwSetHash for a given namespace and collection
    51  func (txRwSet *TxRwSet) GetPvtDataHash(ns, coll string) []byte {
    52  	// we could build and use a map to reduce the number of lookup
    53  	// in the future call. However, we decided to defer such optimization
    54  	// due to the following assumptions (mainly to avoid additional LOC).
    55  	// we assume that the number of namespaces and collections in a txRWSet
    56  	// to be very minimal (in a single digit),
    57  	for _, nsRwSet := range txRwSet.NsRwSets {
    58  		if nsRwSet.NameSpace != ns {
    59  			continue
    60  		}
    61  		return nsRwSet.getPvtDataHash(coll)
    62  	}
    63  	return nil
    64  }
    65  
    66  func (nsRwSet *NsRwSet) getPvtDataHash(coll string) []byte {
    67  	for _, collHashedRwSet := range nsRwSet.CollHashedRwSets {
    68  		if collHashedRwSet.CollectionName != coll {
    69  			continue
    70  		}
    71  		return collHashedRwSet.PvtRwSetHash
    72  	}
    73  	return nil
    74  }
    75  
    76  /////////////////////////////////////////////////////////////////
    77  // Messages related to PRIVATE read-write set
    78  /////////////////////////////////////////////////////////////////
    79  
    80  // TxPvtRwSet represents 'rwset.TxPvtReadWriteSet' proto message
    81  type TxPvtRwSet struct {
    82  	NsPvtRwSet []*NsPvtRwSet
    83  }
    84  
    85  // NsPvtRwSet represents 'rwset.NsPvtReadWriteSet' proto message
    86  type NsPvtRwSet struct {
    87  	NameSpace     string
    88  	CollPvtRwSets []*CollPvtRwSet
    89  }
    90  
    91  // CollPvtRwSet encapsulates 'kvrwset.KVRWSet' proto message for a private rwset for a specific collection
    92  // KvRwSet in a private RwSet should not contain range query info
    93  type CollPvtRwSet struct {
    94  	CollectionName string
    95  	KvRwSet        *kvrwset.KVRWSet
    96  }
    97  
    98  /////////////////////////////////////////////////////////////////
    99  // FUNCTIONS for converting messages to/from proto bytes
   100  /////////////////////////////////////////////////////////////////
   101  
   102  // ToProtoBytes constructs TxReadWriteSet proto message and serializes using protobuf Marshal
   103  func (txRwSet *TxRwSet) ToProtoBytes() ([]byte, error) {
   104  	var protoMsg *rwset.TxReadWriteSet
   105  	var err error
   106  	if protoMsg, err = txRwSet.toProtoMsg(); err != nil {
   107  		return nil, err
   108  	}
   109  	return proto.Marshal(protoMsg)
   110  }
   111  
   112  // FromProtoBytes deserializes protobytes into TxReadWriteSet proto message and populates 'TxRwSet'
   113  func (txRwSet *TxRwSet) FromProtoBytes(protoBytes []byte) error {
   114  	protoMsg := &rwset.TxReadWriteSet{}
   115  	var err error
   116  	var txRwSetTemp *TxRwSet
   117  	if err = proto.Unmarshal(protoBytes, protoMsg); err != nil {
   118  		return err
   119  	}
   120  	if txRwSetTemp, err = TxRwSetFromProtoMsg(protoMsg); err != nil {
   121  		return err
   122  	}
   123  	txRwSet.NsRwSets = txRwSetTemp.NsRwSets
   124  	return nil
   125  }
   126  
   127  // ToProtoBytes constructs 'TxPvtReadWriteSet' proto message and serializes using protobuf Marshal
   128  func (txPvtRwSet *TxPvtRwSet) ToProtoBytes() ([]byte, error) {
   129  	var protoMsg *rwset.TxPvtReadWriteSet
   130  	var err error
   131  	if protoMsg, err = txPvtRwSet.toProtoMsg(); err != nil {
   132  		return nil, err
   133  	}
   134  	return proto.Marshal(protoMsg)
   135  }
   136  
   137  // FromProtoBytes deserializes protobytes into 'TxPvtReadWriteSet' proto message and populates 'TxPvtRwSet'
   138  func (txPvtRwSet *TxPvtRwSet) FromProtoBytes(protoBytes []byte) error {
   139  	protoMsg := &rwset.TxPvtReadWriteSet{}
   140  	var err error
   141  	var txPvtRwSetTemp *TxPvtRwSet
   142  	if err = proto.Unmarshal(protoBytes, protoMsg); err != nil {
   143  		return err
   144  	}
   145  	if txPvtRwSetTemp, err = TxPvtRwSetFromProtoMsg(protoMsg); err != nil {
   146  		return err
   147  	}
   148  	txPvtRwSet.NsPvtRwSet = txPvtRwSetTemp.NsPvtRwSet
   149  	return nil
   150  }
   151  
   152  func (txRwSet *TxRwSet) toProtoMsg() (*rwset.TxReadWriteSet, error) {
   153  	protoMsg := &rwset.TxReadWriteSet{DataModel: rwset.TxReadWriteSet_KV}
   154  	var nsRwSetProtoMsg *rwset.NsReadWriteSet
   155  	var err error
   156  	for _, nsRwSet := range txRwSet.NsRwSets {
   157  		if nsRwSetProtoMsg, err = nsRwSet.toProtoMsg(); err != nil {
   158  			return nil, err
   159  		}
   160  		protoMsg.NsRwset = append(protoMsg.NsRwset, nsRwSetProtoMsg)
   161  	}
   162  	return protoMsg, nil
   163  }
   164  
   165  func TxRwSetFromProtoMsg(protoMsg *rwset.TxReadWriteSet) (*TxRwSet, error) {
   166  	txRwSet := &TxRwSet{}
   167  	var nsRwSet *NsRwSet
   168  	var err error
   169  	for _, nsRwSetProtoMsg := range protoMsg.NsRwset {
   170  		if nsRwSet, err = nsRwSetFromProtoMsg(nsRwSetProtoMsg); err != nil {
   171  			return nil, err
   172  		}
   173  		txRwSet.NsRwSets = append(txRwSet.NsRwSets, nsRwSet)
   174  	}
   175  	return txRwSet, nil
   176  }
   177  
   178  func (nsRwSet *NsRwSet) toProtoMsg() (*rwset.NsReadWriteSet, error) {
   179  	var err error
   180  	protoMsg := &rwset.NsReadWriteSet{Namespace: nsRwSet.NameSpace}
   181  	if protoMsg.Rwset, err = proto.Marshal(nsRwSet.KvRwSet); err != nil {
   182  		return nil, err
   183  	}
   184  
   185  	var collHashedRwSetProtoMsg *rwset.CollectionHashedReadWriteSet
   186  	for _, collHashedRwSet := range nsRwSet.CollHashedRwSets {
   187  		if collHashedRwSetProtoMsg, err = collHashedRwSet.toProtoMsg(); err != nil {
   188  			return nil, err
   189  		}
   190  		protoMsg.CollectionHashedRwset = append(protoMsg.CollectionHashedRwset, collHashedRwSetProtoMsg)
   191  	}
   192  	return protoMsg, nil
   193  }
   194  
   195  func nsRwSetFromProtoMsg(protoMsg *rwset.NsReadWriteSet) (*NsRwSet, error) {
   196  	nsRwSet := &NsRwSet{NameSpace: protoMsg.Namespace, KvRwSet: &kvrwset.KVRWSet{}}
   197  	if err := proto.Unmarshal(protoMsg.Rwset, nsRwSet.KvRwSet); err != nil {
   198  		return nil, err
   199  	}
   200  	var err error
   201  	var collHashedRwSet *CollHashedRwSet
   202  	for _, collHashedRwSetProtoMsg := range protoMsg.CollectionHashedRwset {
   203  		if collHashedRwSet, err = collHashedRwSetFromProtoMsg(collHashedRwSetProtoMsg); err != nil {
   204  			return nil, err
   205  		}
   206  		nsRwSet.CollHashedRwSets = append(nsRwSet.CollHashedRwSets, collHashedRwSet)
   207  	}
   208  	return nsRwSet, nil
   209  }
   210  
   211  func (collHashedRwSet *CollHashedRwSet) toProtoMsg() (*rwset.CollectionHashedReadWriteSet, error) {
   212  	var err error
   213  	protoMsg := &rwset.CollectionHashedReadWriteSet{
   214  		CollectionName: collHashedRwSet.CollectionName,
   215  		PvtRwsetHash:   collHashedRwSet.PvtRwSetHash,
   216  	}
   217  	if protoMsg.HashedRwset, err = proto.Marshal(collHashedRwSet.HashedRwSet); err != nil {
   218  		return nil, err
   219  	}
   220  	return protoMsg, nil
   221  }
   222  
   223  func collHashedRwSetFromProtoMsg(protoMsg *rwset.CollectionHashedReadWriteSet) (*CollHashedRwSet, error) {
   224  	colHashedRwSet := &CollHashedRwSet{
   225  		CollectionName: protoMsg.CollectionName,
   226  		PvtRwSetHash:   protoMsg.PvtRwsetHash,
   227  		HashedRwSet:    &kvrwset.HashedRWSet{},
   228  	}
   229  	if err := proto.Unmarshal(protoMsg.HashedRwset, colHashedRwSet.HashedRwSet); err != nil {
   230  		return nil, err
   231  	}
   232  	return colHashedRwSet, nil
   233  }
   234  
   235  func (txRwSet *TxRwSet) NumCollections() int {
   236  	if txRwSet == nil {
   237  		return 0
   238  	}
   239  	numColls := 0
   240  	for _, nsRwset := range txRwSet.NsRwSets {
   241  		for range nsRwset.CollHashedRwSets {
   242  			numColls++
   243  		}
   244  	}
   245  	return numColls
   246  }
   247  
   248  ///////////////////////////////////////////////////////////////////////////////
   249  // functions for private read-write set
   250  ///////////////////////////////////////////////////////////////////////////////
   251  
   252  func (txPvtRwSet *TxPvtRwSet) toProtoMsg() (*rwset.TxPvtReadWriteSet, error) {
   253  	protoMsg := &rwset.TxPvtReadWriteSet{DataModel: rwset.TxReadWriteSet_KV}
   254  	var nsProtoMsg *rwset.NsPvtReadWriteSet
   255  	var err error
   256  	for _, nsPvtRwSet := range txPvtRwSet.NsPvtRwSet {
   257  		if nsProtoMsg, err = nsPvtRwSet.toProtoMsg(); err != nil {
   258  			return nil, err
   259  		}
   260  		protoMsg.NsPvtRwset = append(protoMsg.NsPvtRwset, nsProtoMsg)
   261  	}
   262  	return protoMsg, nil
   263  }
   264  
   265  func TxPvtRwSetFromProtoMsg(protoMsg *rwset.TxPvtReadWriteSet) (*TxPvtRwSet, error) {
   266  	txPvtRwset := &TxPvtRwSet{}
   267  	var nsPvtRwSet *NsPvtRwSet
   268  	var err error
   269  	for _, nsRwSetProtoMsg := range protoMsg.NsPvtRwset {
   270  		if nsPvtRwSet, err = nsPvtRwSetFromProtoMsg(nsRwSetProtoMsg); err != nil {
   271  			return nil, err
   272  		}
   273  		txPvtRwset.NsPvtRwSet = append(txPvtRwset.NsPvtRwSet, nsPvtRwSet)
   274  	}
   275  	return txPvtRwset, nil
   276  }
   277  
   278  func (nsPvtRwSet *NsPvtRwSet) toProtoMsg() (*rwset.NsPvtReadWriteSet, error) {
   279  	protoMsg := &rwset.NsPvtReadWriteSet{Namespace: nsPvtRwSet.NameSpace}
   280  	var err error
   281  	var collPvtRwSetProtoMsg *rwset.CollectionPvtReadWriteSet
   282  	for _, collPvtRwSet := range nsPvtRwSet.CollPvtRwSets {
   283  		if collPvtRwSetProtoMsg, err = collPvtRwSet.toProtoMsg(); err != nil {
   284  			return nil, err
   285  		}
   286  		protoMsg.CollectionPvtRwset = append(protoMsg.CollectionPvtRwset, collPvtRwSetProtoMsg)
   287  	}
   288  	return protoMsg, err
   289  }
   290  
   291  func nsPvtRwSetFromProtoMsg(protoMsg *rwset.NsPvtReadWriteSet) (*NsPvtRwSet, error) {
   292  	nsPvtRwSet := &NsPvtRwSet{NameSpace: protoMsg.Namespace}
   293  	for _, collPvtRwSetProtoMsg := range protoMsg.CollectionPvtRwset {
   294  		var err error
   295  		var collPvtRwSet *CollPvtRwSet
   296  		if collPvtRwSet, err = collPvtRwSetFromProtoMsg(collPvtRwSetProtoMsg); err != nil {
   297  			return nil, err
   298  		}
   299  		nsPvtRwSet.CollPvtRwSets = append(nsPvtRwSet.CollPvtRwSets, collPvtRwSet)
   300  	}
   301  	return nsPvtRwSet, nil
   302  }
   303  
   304  func (collPvtRwSet *CollPvtRwSet) toProtoMsg() (*rwset.CollectionPvtReadWriteSet, error) {
   305  	var err error
   306  	protoMsg := &rwset.CollectionPvtReadWriteSet{CollectionName: collPvtRwSet.CollectionName}
   307  	if protoMsg.Rwset, err = proto.Marshal(collPvtRwSet.KvRwSet); err != nil {
   308  		return nil, err
   309  	}
   310  	return protoMsg, nil
   311  }
   312  
   313  func collPvtRwSetFromProtoMsg(protoMsg *rwset.CollectionPvtReadWriteSet) (*CollPvtRwSet, error) {
   314  	collPvtRwSet := &CollPvtRwSet{CollectionName: protoMsg.CollectionName, KvRwSet: &kvrwset.KVRWSet{}}
   315  	if err := proto.Unmarshal(protoMsg.Rwset, collPvtRwSet.KvRwSet); err != nil {
   316  		return nil, err
   317  	}
   318  	return collPvtRwSet, nil
   319  }
   320  
   321  // NewKVRead helps constructing proto message kvrwset.KVRead
   322  func NewKVRead(key string, version *version.Height) *kvrwset.KVRead {
   323  	return &kvrwset.KVRead{Key: key, Version: newProtoVersion(version)}
   324  }
   325  
   326  // NewVersion helps converting proto message kvrwset.Version to version.Height
   327  func NewVersion(protoVersion *kvrwset.Version) *version.Height {
   328  	if protoVersion == nil {
   329  		return nil
   330  	}
   331  	return version.NewHeight(protoVersion.BlockNum, protoVersion.TxNum)
   332  }
   333  
   334  func newProtoVersion(height *version.Height) *kvrwset.Version {
   335  	if height == nil {
   336  		return nil
   337  	}
   338  	return &kvrwset.Version{BlockNum: height.BlockNum, TxNum: height.TxNum}
   339  }
   340  
   341  func newKVWrite(key string, value []byte) *kvrwset.KVWrite {
   342  	return &kvrwset.KVWrite{Key: key, IsDelete: value == nil, Value: value}
   343  }
   344  
   345  func newPvtKVReadHash(key string, version *version.Height) *kvrwset.KVReadHash {
   346  	return &kvrwset.KVReadHash{KeyHash: util.ComputeStringHash(key), Version: newProtoVersion(version)}
   347  }
   348  
   349  func newPvtKVWriteAndHash(key string, value []byte) (*kvrwset.KVWrite, *kvrwset.KVWriteHash) {
   350  	kvWrite := newKVWrite(key, value)
   351  	var keyHash, valueHash []byte
   352  	keyHash = util.ComputeStringHash(key)
   353  	if !kvWrite.IsDelete {
   354  		valueHash = util.ComputeHash(value)
   355  	}
   356  	return kvWrite, &kvrwset.KVWriteHash{KeyHash: keyHash, IsDelete: kvWrite.IsDelete, ValueHash: valueHash}
   357  }