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 }