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 }