github.com/osdi23p228/fabric@v0.0.0-20221218062954-77808885f5db/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  	"bytes"
    21  
    22  	"github.com/golang/protobuf/proto"
    23  	"github.com/hyperledger/fabric-protos-go/ledger/rwset"
    24  	"github.com/hyperledger/fabric-protos-go/ledger/rwset/kvrwset"
    25  	"github.com/osdi23p228/fabric/core/ledger/internal/version"
    26  	"github.com/osdi23p228/fabric/core/ledger/util"
    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  func TxRwSetFromProtoMsg(protoMsg *rwset.TxReadWriteSet) (*TxRwSet, error) {
   168  	txRwSet := &TxRwSet{}
   169  	var nsRwSet *NsRwSet
   170  	var err error
   171  	for _, nsRwSetProtoMsg := range protoMsg.NsRwset {
   172  		if nsRwSet, err = nsRwSetFromProtoMsg(nsRwSetProtoMsg); err != nil {
   173  			return nil, err
   174  		}
   175  		txRwSet.NsRwSets = append(txRwSet.NsRwSets, nsRwSet)
   176  	}
   177  	return txRwSet, nil
   178  }
   179  
   180  func (nsRwSet *NsRwSet) toProtoMsg() (*rwset.NsReadWriteSet, error) {
   181  	var err error
   182  	protoMsg := &rwset.NsReadWriteSet{Namespace: nsRwSet.NameSpace}
   183  	if protoMsg.Rwset, err = proto.Marshal(nsRwSet.KvRwSet); err != nil {
   184  		return nil, err
   185  	}
   186  
   187  	var collHashedRwSetProtoMsg *rwset.CollectionHashedReadWriteSet
   188  	for _, collHashedRwSet := range nsRwSet.CollHashedRwSets {
   189  		if collHashedRwSetProtoMsg, err = collHashedRwSet.toProtoMsg(); err != nil {
   190  			return nil, err
   191  		}
   192  		protoMsg.CollectionHashedRwset = append(protoMsg.CollectionHashedRwset, collHashedRwSetProtoMsg)
   193  	}
   194  	return protoMsg, nil
   195  }
   196  
   197  func nsRwSetFromProtoMsg(protoMsg *rwset.NsReadWriteSet) (*NsRwSet, error) {
   198  	nsRwSet := &NsRwSet{NameSpace: protoMsg.Namespace, KvRwSet: &kvrwset.KVRWSet{}}
   199  	if err := proto.Unmarshal(protoMsg.Rwset, nsRwSet.KvRwSet); err != nil {
   200  		return nil, err
   201  	}
   202  	var err error
   203  	var collHashedRwSet *CollHashedRwSet
   204  	for _, collHashedRwSetProtoMsg := range protoMsg.CollectionHashedRwset {
   205  		if collHashedRwSet, err = collHashedRwSetFromProtoMsg(collHashedRwSetProtoMsg); err != nil {
   206  			return nil, err
   207  		}
   208  		nsRwSet.CollHashedRwSets = append(nsRwSet.CollHashedRwSets, collHashedRwSet)
   209  	}
   210  	return nsRwSet, nil
   211  }
   212  
   213  func (collHashedRwSet *CollHashedRwSet) toProtoMsg() (*rwset.CollectionHashedReadWriteSet, error) {
   214  	var err error
   215  	protoMsg := &rwset.CollectionHashedReadWriteSet{
   216  		CollectionName: collHashedRwSet.CollectionName,
   217  		PvtRwsetHash:   collHashedRwSet.PvtRwSetHash,
   218  	}
   219  	if protoMsg.HashedRwset, err = proto.Marshal(collHashedRwSet.HashedRwSet); err != nil {
   220  		return nil, err
   221  	}
   222  	return protoMsg, nil
   223  }
   224  
   225  func collHashedRwSetFromProtoMsg(protoMsg *rwset.CollectionHashedReadWriteSet) (*CollHashedRwSet, error) {
   226  	colHashedRwSet := &CollHashedRwSet{
   227  		CollectionName: protoMsg.CollectionName,
   228  		PvtRwSetHash:   protoMsg.PvtRwsetHash,
   229  		HashedRwSet:    &kvrwset.HashedRWSet{},
   230  	}
   231  	if err := proto.Unmarshal(protoMsg.HashedRwset, colHashedRwSet.HashedRwSet); err != nil {
   232  		return nil, err
   233  	}
   234  	return colHashedRwSet, nil
   235  }
   236  
   237  func (txRwSet *TxRwSet) NumCollections() int {
   238  	if txRwSet == nil {
   239  		return 0
   240  	}
   241  	numColls := 0
   242  	for _, nsRwset := range txRwSet.NsRwSets {
   243  		for range nsRwset.CollHashedRwSets {
   244  			numColls++
   245  		}
   246  	}
   247  	return numColls
   248  }
   249  
   250  ///////////////////////////////////////////////////////////////////////////////
   251  // functions for private read-write set
   252  ///////////////////////////////////////////////////////////////////////////////
   253  
   254  func (txPvtRwSet *TxPvtRwSet) toProtoMsg() (*rwset.TxPvtReadWriteSet, error) {
   255  	protoMsg := &rwset.TxPvtReadWriteSet{DataModel: rwset.TxReadWriteSet_KV}
   256  	var nsProtoMsg *rwset.NsPvtReadWriteSet
   257  	var err error
   258  	for _, nsPvtRwSet := range txPvtRwSet.NsPvtRwSet {
   259  		if nsProtoMsg, err = nsPvtRwSet.toProtoMsg(); err != nil {
   260  			return nil, err
   261  		}
   262  		protoMsg.NsPvtRwset = append(protoMsg.NsPvtRwset, nsProtoMsg)
   263  	}
   264  	return protoMsg, nil
   265  }
   266  
   267  func TxPvtRwSetFromProtoMsg(protoMsg *rwset.TxPvtReadWriteSet) (*TxPvtRwSet, error) {
   268  	txPvtRwset := &TxPvtRwSet{}
   269  	var nsPvtRwSet *NsPvtRwSet
   270  	var err error
   271  	for _, nsRwSetProtoMsg := range protoMsg.NsPvtRwset {
   272  		if nsPvtRwSet, err = nsPvtRwSetFromProtoMsg(nsRwSetProtoMsg); err != nil {
   273  			return nil, err
   274  		}
   275  		txPvtRwset.NsPvtRwSet = append(txPvtRwset.NsPvtRwSet, nsPvtRwSet)
   276  	}
   277  	return txPvtRwset, nil
   278  }
   279  
   280  func (nsPvtRwSet *NsPvtRwSet) toProtoMsg() (*rwset.NsPvtReadWriteSet, error) {
   281  	protoMsg := &rwset.NsPvtReadWriteSet{Namespace: nsPvtRwSet.NameSpace}
   282  	var err error
   283  	var collPvtRwSetProtoMsg *rwset.CollectionPvtReadWriteSet
   284  	for _, collPvtRwSet := range nsPvtRwSet.CollPvtRwSets {
   285  		if collPvtRwSetProtoMsg, err = collPvtRwSet.toProtoMsg(); err != nil {
   286  			return nil, err
   287  		}
   288  		protoMsg.CollectionPvtRwset = append(protoMsg.CollectionPvtRwset, collPvtRwSetProtoMsg)
   289  	}
   290  	return protoMsg, err
   291  }
   292  
   293  func nsPvtRwSetFromProtoMsg(protoMsg *rwset.NsPvtReadWriteSet) (*NsPvtRwSet, error) {
   294  	nsPvtRwSet := &NsPvtRwSet{NameSpace: protoMsg.Namespace}
   295  	for _, collPvtRwSetProtoMsg := range protoMsg.CollectionPvtRwset {
   296  		var err error
   297  		var collPvtRwSet *CollPvtRwSet
   298  		if collPvtRwSet, err = collPvtRwSetFromProtoMsg(collPvtRwSetProtoMsg); err != nil {
   299  			return nil, err
   300  		}
   301  		nsPvtRwSet.CollPvtRwSets = append(nsPvtRwSet.CollPvtRwSets, collPvtRwSet)
   302  	}
   303  	return nsPvtRwSet, nil
   304  }
   305  
   306  func (collPvtRwSet *CollPvtRwSet) toProtoMsg() (*rwset.CollectionPvtReadWriteSet, error) {
   307  	var err error
   308  	protoMsg := &rwset.CollectionPvtReadWriteSet{CollectionName: collPvtRwSet.CollectionName}
   309  	if protoMsg.Rwset, err = proto.Marshal(collPvtRwSet.KvRwSet); err != nil {
   310  		return nil, err
   311  	}
   312  	return protoMsg, nil
   313  }
   314  
   315  func collPvtRwSetFromProtoMsg(protoMsg *rwset.CollectionPvtReadWriteSet) (*CollPvtRwSet, error) {
   316  	collPvtRwSet := &CollPvtRwSet{CollectionName: protoMsg.CollectionName, KvRwSet: &kvrwset.KVRWSet{}}
   317  	if err := proto.Unmarshal(protoMsg.Rwset, collPvtRwSet.KvRwSet); err != nil {
   318  		return nil, err
   319  	}
   320  	return collPvtRwSet, nil
   321  }
   322  
   323  // NewKVRead helps constructing proto message kvrwset.KVRead
   324  func NewKVRead(key string, version *version.Height) *kvrwset.KVRead {
   325  	return &kvrwset.KVRead{Key: key, Version: newProtoVersion(version)}
   326  }
   327  
   328  // NewVersion helps converting proto message kvrwset.Version to version.Height
   329  func NewVersion(protoVersion *kvrwset.Version) *version.Height {
   330  	if protoVersion == nil {
   331  		return nil
   332  	}
   333  	return version.NewHeight(protoVersion.BlockNum, protoVersion.TxNum)
   334  }
   335  
   336  func newProtoVersion(height *version.Height) *kvrwset.Version {
   337  	if height == nil {
   338  		return nil
   339  	}
   340  	return &kvrwset.Version{BlockNum: height.BlockNum, TxNum: height.TxNum}
   341  }
   342  
   343  func newKVWrite(key string, value []byte) *kvrwset.KVWrite {
   344  	return &kvrwset.KVWrite{Key: key, IsDelete: len(value) == 0, Value: value}
   345  }
   346  
   347  func newPvtKVReadHash(key string, version *version.Height) *kvrwset.KVReadHash {
   348  	return &kvrwset.KVReadHash{KeyHash: util.ComputeStringHash(key), Version: newProtoVersion(version)}
   349  }
   350  
   351  func newPvtKVWriteAndHash(key string, value []byte) (*kvrwset.KVWrite, *kvrwset.KVWriteHash) {
   352  	kvWrite := newKVWrite(key, value)
   353  	var keyHash, valueHash []byte
   354  	keyHash = util.ComputeStringHash(key)
   355  	if !kvWrite.IsDelete {
   356  		valueHash = util.ComputeHash(value)
   357  	}
   358  	return kvWrite, &kvrwset.KVWriteHash{KeyHash: keyHash, IsDelete: kvWrite.IsDelete, ValueHash: valueHash}
   359  }
   360  
   361  // IsKVWriteDelete returns true if the kvWrite indicates a delete operation. See FAB-18386 for details.
   362  func IsKVWriteDelete(kvWrite *kvrwset.KVWrite) bool {
   363  	return kvWrite.IsDelete || len(kvWrite.Value) == 0
   364  }
   365  
   366  var (
   367  	hashOfZeroLengthByteArray = util.ComputeHash([]byte{})
   368  )
   369  
   370  // IsKVWriteHashDelete returns true if the kvWriteHash indicates a delete operation. See FAB-18386 for details.
   371  func IsKVWriteHashDelete(kvWriteHash *kvrwset.KVWriteHash) bool {
   372  	return kvWriteHash.IsDelete || len(kvWriteHash.ValueHash) == 0 || bytes.Equal(hashOfZeroLengthByteArray, kvWriteHash.ValueHash)
   373  }