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