github.com/hechain20/hechain@v0.0.0-20220316014945-b544036ba106/core/ledger/kvledger/txmgmt/validation/rangequery_validator.go (about)

     1  /*
     2  Copyright hechain. 2022 All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package validation
     8  
     9  import (
    10  	"bytes"
    11  
    12  	"github.com/hechain20/hechain/core/ledger/internal/version"
    13  	"github.com/hechain20/hechain/core/ledger/kvledger/txmgmt/rwsetutil"
    14  	"github.com/hechain20/hechain/core/ledger/kvledger/txmgmt/statedb"
    15  	"github.com/hyperledger/fabric-protos-go/ledger/rwset/kvrwset"
    16  )
    17  
    18  type rangeQueryValidator interface {
    19  	init(rqInfo *kvrwset.RangeQueryInfo, itr statedb.ResultsIterator) error
    20  	validate() (bool, error)
    21  }
    22  
    23  type rangeQueryResultsValidator struct {
    24  	rqInfo *kvrwset.RangeQueryInfo
    25  	itr    statedb.ResultsIterator
    26  }
    27  
    28  func (v *rangeQueryResultsValidator) init(rqInfo *kvrwset.RangeQueryInfo, itr statedb.ResultsIterator) error {
    29  	v.rqInfo = rqInfo
    30  	v.itr = itr
    31  	return nil
    32  }
    33  
    34  // validate iterates through the results that are present in the range-query-info (captured during simulation)
    35  // and the iterator (latest view of the `committed state` i.e., db + updates). At first mismatch between the results
    36  // from the two sources (the range-query-info and the iterator), the validate returns false.
    37  func (v *rangeQueryResultsValidator) validate() (bool, error) {
    38  	rqResults := v.rqInfo.GetRawReads().GetKvReads()
    39  	itr := v.itr
    40  	var result *statedb.VersionedKV
    41  	var err error
    42  	if result, err = itr.Next(); err != nil {
    43  		return false, err
    44  	}
    45  	if len(rqResults) == 0 {
    46  		return result == nil, nil
    47  	}
    48  	for i := 0; i < len(rqResults); i++ {
    49  		kvRead := rqResults[i]
    50  		logger.Debugf("comparing kvRead=[%#v] to queryResponse=[%#v]", kvRead, result)
    51  		if result == nil {
    52  			logger.Debugf("Query response nil. Key [%s] got deleted", kvRead.Key)
    53  			return false, nil
    54  		}
    55  
    56  		if result.Key != kvRead.Key {
    57  			logger.Debugf("key name mismatch: Key in rwset = [%s], key in query results = [%s]", kvRead.Key, result.Key)
    58  			return false, nil
    59  		}
    60  		if !version.AreSame(result.Version, convertToVersionHeight(kvRead.Version)) {
    61  			logger.Debugf(`Version mismatch for key [%s]: Version in rwset = [%#v], latest version = [%#v]`,
    62  				result.Key, result.Version, kvRead.Version)
    63  			return false, nil
    64  		}
    65  		if result, err = itr.Next(); err != nil {
    66  			return false, err
    67  		}
    68  	}
    69  	if result != nil {
    70  		// iterator is not exhausted - which means that there are extra results in the given range
    71  		logger.Debugf("Extra result = [%#v]", result)
    72  		return false, nil
    73  	}
    74  	return true, nil
    75  }
    76  
    77  type rangeQueryHashValidator struct {
    78  	rqInfo        *kvrwset.RangeQueryInfo
    79  	itr           statedb.ResultsIterator
    80  	resultsHelper *rwsetutil.RangeQueryResultsHelper
    81  	hashFunc      rwsetutil.HashFunc
    82  }
    83  
    84  func (v *rangeQueryHashValidator) init(rqInfo *kvrwset.RangeQueryInfo, itr statedb.ResultsIterator) error {
    85  	v.rqInfo = rqInfo
    86  	v.itr = itr
    87  	var err error
    88  	v.resultsHelper, err = rwsetutil.NewRangeQueryResultsHelper(true, rqInfo.GetReadsMerkleHashes().MaxDegree, v.hashFunc)
    89  	return err
    90  }
    91  
    92  // validate iterates through the iterator (latest view of the `committed state` i.e., db + updates)
    93  // and starts building the merkle tree incrementally (Both, during simulation and during validation,
    94  // rwset.RangeQueryResultsHelper is used for building the merkle tree incrementally ).
    95  //
    96  // This function also keeps comparing the under-construction merkle tree with the merkle tree
    97  // summary present in the range-query-info (built during simulation).
    98  // This function returns false on first mismatch between the nodes of the two merkle trees
    99  // at the desired level (the maxLevel of the merkle tree in range-query-info).
   100  func (v *rangeQueryHashValidator) validate() (bool, error) {
   101  	itr := v.itr
   102  	lastMatchedIndex := -1
   103  	inMerkle := v.rqInfo.GetReadsMerkleHashes()
   104  	var merkle *kvrwset.QueryReadsMerkleSummary
   105  	logger.Debugf("inMerkle: %#v", inMerkle)
   106  	for {
   107  		var result *statedb.VersionedKV
   108  		var err error
   109  		if result, err = itr.Next(); err != nil {
   110  			return false, err
   111  		}
   112  		logger.Debugf("Processing result = %#v", result)
   113  		if result == nil {
   114  			if _, merkle, err = v.resultsHelper.Done(); err != nil {
   115  				return false, err
   116  			}
   117  			equals := merkleSummariesEqual(inMerkle, merkle)
   118  			logger.Debugf("Combined iterator exhausted. merkle=%#v, equals=%t", merkle, equals)
   119  			return equals, nil
   120  		}
   121  
   122  		if err := v.resultsHelper.AddResult(rwsetutil.NewKVRead(result.Key, result.Version)); err != nil {
   123  			return false, err
   124  		}
   125  		merkle := v.resultsHelper.GetMerkleSummary()
   126  
   127  		if merkle.MaxLevel < inMerkle.MaxLevel {
   128  			logger.Debugf("Hashes still under construction. Noting to compare yet. Need more results. Continuing...")
   129  			continue
   130  		}
   131  		if lastMatchedIndex == len(merkle.MaxLevelHashes)-1 {
   132  			logger.Debugf("Need more results to build next entry [index=%d] at level [%d]. Continuing...",
   133  				lastMatchedIndex+1, merkle.MaxLevel)
   134  			continue
   135  		}
   136  		if len(merkle.MaxLevelHashes) > len(inMerkle.MaxLevelHashes) {
   137  			logger.Debugf("Entries exceeded from what are present in the incoming merkleSummary. Validation failed")
   138  			return false, nil
   139  		}
   140  		lastMatchedIndex++
   141  		if !bytes.Equal(merkle.MaxLevelHashes[lastMatchedIndex], inMerkle.MaxLevelHashes[lastMatchedIndex]) {
   142  			logger.Debugf("Hashes does not match at index [%d]. Validation failed", lastMatchedIndex)
   143  			return false, nil
   144  		}
   145  	}
   146  }
   147  
   148  func merkleSummariesEqual(ms, anotherMS *kvrwset.QueryReadsMerkleSummary) bool {
   149  	if anotherMS == nil {
   150  		return false
   151  	}
   152  	if ms.MaxDegree != anotherMS.MaxDegree ||
   153  		ms.MaxLevel != anotherMS.MaxLevel ||
   154  		len(ms.MaxLevelHashes) != len(anotherMS.MaxLevelHashes) {
   155  		return false
   156  	}
   157  	for i := 0; i < len(ms.MaxLevelHashes); i++ {
   158  		if !bytes.Equal(ms.MaxLevelHashes[i], anotherMS.MaxLevelHashes[i]) {
   159  			return false
   160  		}
   161  	}
   162  	return true
   163  }
   164  
   165  func convertToVersionHeight(v *kvrwset.Version) *version.Height {
   166  	return version.NewHeight(v.BlockNum, v.TxNum)
   167  }