github.com/Hnampk/fabric@v2.1.1+incompatible/core/ledger/kvledger/txmgmt/validator/internal/val.go (about) 1 /* 2 Copyright IBM Corp. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package internal 8 9 import ( 10 "github.com/hyperledger/fabric-protos-go/peer" 11 "github.com/hyperledger/fabric/common/flogging" 12 "github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt/privacyenabledstate" 13 "github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt/rwsetutil" 14 "github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt/version" 15 ) 16 17 var logger = flogging.MustGetLogger("valinternal") 18 19 // Validator is supposed to validate the transactions based on public data and hashes present in a block 20 // and returns a batch that should be used to update the state 21 type Validator interface { 22 ValidateAndPrepareBatch(block *Block, doMVCCValidation bool) (*PubAndHashUpdates, error) 23 } 24 25 // Block is used to used to hold the information from its proto format to a structure 26 // that is more suitable/friendly for validation 27 type Block struct { 28 Num uint64 29 Txs []*Transaction 30 } 31 32 // Transaction is used to hold the information from its proto format to a structure 33 // that is more suitable/friendly for validation 34 type Transaction struct { 35 IndexInBlock int 36 ID string 37 RWSet *rwsetutil.TxRwSet 38 ValidationCode peer.TxValidationCode 39 ContainsPostOrderWrites bool 40 } 41 42 // PubAndHashUpdates encapsulates public and hash updates. The intended use of this to hold the updates 43 // that are to be applied to the statedb as a result of the block commit 44 type PubAndHashUpdates struct { 45 PubUpdates *privacyenabledstate.PubUpdateBatch 46 HashUpdates *privacyenabledstate.HashedUpdateBatch 47 } 48 49 // NewPubAndHashUpdates constructs an empty PubAndHashUpdates 50 func NewPubAndHashUpdates() *PubAndHashUpdates { 51 return &PubAndHashUpdates{ 52 privacyenabledstate.NewPubUpdateBatch(), 53 privacyenabledstate.NewHashedUpdateBatch(), 54 } 55 } 56 57 // ContainsPvtWrites returns true if this transaction is not limited to affecting the public data only 58 func (t *Transaction) ContainsPvtWrites() bool { 59 for _, ns := range t.RWSet.NsRwSets { 60 for _, coll := range ns.CollHashedRwSets { 61 if coll.PvtRwSetHash != nil { 62 return true 63 } 64 } 65 } 66 return false 67 } 68 69 // RetrieveHash returns the hash of the private write-set present 70 // in the public data for a given namespace-collection 71 func (t *Transaction) RetrieveHash(ns string, coll string) []byte { 72 if t.RWSet == nil { 73 return nil 74 } 75 for _, nsData := range t.RWSet.NsRwSets { 76 if nsData.NameSpace != ns { 77 continue 78 } 79 80 for _, collData := range nsData.CollHashedRwSets { 81 if collData.CollectionName == coll { 82 return collData.PvtRwSetHash 83 } 84 } 85 } 86 return nil 87 } 88 89 // ApplyWriteSet adds (or deletes) the key/values present in the write set to the PubAndHashUpdates 90 func (u *PubAndHashUpdates) ApplyWriteSet( 91 txRWSet *rwsetutil.TxRwSet, 92 txHeight *version.Height, 93 db privacyenabledstate.DB, 94 containsPostOrderWrites bool, 95 ) error { 96 u.PubUpdates.ContainsPostOrderWrites = 97 u.PubUpdates.ContainsPostOrderWrites || containsPostOrderWrites 98 txops, err := prepareTxOps(txRWSet, txHeight, u, db) 99 logger.Debugf("txops=%#v", txops) 100 if err != nil { 101 return err 102 } 103 for compositeKey, keyops := range txops { 104 if compositeKey.coll == "" { 105 ns, key := compositeKey.ns, compositeKey.key 106 if keyops.isDelete() { 107 u.PubUpdates.Delete(ns, key, txHeight) 108 } else { 109 u.PubUpdates.PutValAndMetadata(ns, key, keyops.value, keyops.metadata, txHeight) 110 } 111 } else { 112 ns, coll, keyHash := compositeKey.ns, compositeKey.coll, []byte(compositeKey.key) 113 if keyops.isDelete() { 114 u.HashUpdates.Delete(ns, coll, keyHash, txHeight) 115 } else { 116 u.HashUpdates.PutValHashAndMetadata(ns, coll, keyHash, keyops.value, keyops.metadata, txHeight) 117 } 118 } 119 } 120 return nil 121 }