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  }