github.com/hechain20/hechain@v0.0.0-20220316014945-b544036ba106/core/ledger/kvledger/txmgmt/rwsetutil/rwset_proto_util.go (about)

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