github.com/Hnampk/fabric@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 }