github.com/badrootd/nibiru-cometbft@v0.37.5-0.20240307173500-2a75559eee9b/state/indexer/block/kv/util.go (about)

     1  package kv
     2  
     3  import (
     4  	"encoding/binary"
     5  	"fmt"
     6  	"math/big"
     7  	"strconv"
     8  
     9  	"github.com/google/orderedcode"
    10  
    11  	"github.com/badrootd/nibiru-cometbft/libs/pubsub/query"
    12  	"github.com/badrootd/nibiru-cometbft/state/indexer"
    13  	"github.com/badrootd/nibiru-cometbft/types"
    14  )
    15  
    16  type HeightInfo struct {
    17  	heightRange     indexer.QueryRange
    18  	height          int64
    19  	heightEqIdx     int
    20  	onlyHeightRange bool
    21  	onlyHeightEq    bool
    22  }
    23  
    24  func intInSlice(a int, list []int) bool {
    25  	for _, b := range list {
    26  		if b == a {
    27  			return true
    28  		}
    29  	}
    30  
    31  	return false
    32  }
    33  
    34  func int64FromBytes(bz []byte) int64 {
    35  	v, _ := binary.Varint(bz)
    36  	return v
    37  }
    38  
    39  func int64ToBytes(i int64) []byte {
    40  	buf := make([]byte, binary.MaxVarintLen64)
    41  	n := binary.PutVarint(buf, i)
    42  	return buf[:n]
    43  }
    44  
    45  func heightKey(height int64) ([]byte, error) {
    46  	return orderedcode.Append(
    47  		nil,
    48  		types.BlockHeightKey,
    49  		height,
    50  	)
    51  }
    52  
    53  func eventKey(compositeKey, typ, eventValue string, height int64, eventSeq int64) ([]byte, error) {
    54  	return orderedcode.Append(
    55  		nil,
    56  		compositeKey,
    57  		eventValue,
    58  		height,
    59  		typ,
    60  		eventSeq,
    61  	)
    62  }
    63  
    64  func parseValueFromPrimaryKey(key []byte) (string, error) {
    65  	var (
    66  		compositeKey string
    67  		height       int64
    68  	)
    69  
    70  	remaining, err := orderedcode.Parse(string(key), &compositeKey, &height)
    71  	if err != nil {
    72  		return "", fmt.Errorf("failed to parse event key: %w", err)
    73  	}
    74  
    75  	if len(remaining) != 0 {
    76  		return "", fmt.Errorf("unexpected remainder in key: %s", remaining)
    77  	}
    78  
    79  	return strconv.FormatInt(height, 10), nil
    80  }
    81  
    82  func parseValueFromEventKey(key []byte) (string, error) {
    83  	var (
    84  		compositeKey, typ, eventValue string
    85  		height                        int64
    86  	)
    87  
    88  	_, err := orderedcode.Parse(string(key), &compositeKey, &eventValue, &height, &typ)
    89  	if err != nil {
    90  		return "", fmt.Errorf("failed to parse event key: %w", err)
    91  	}
    92  
    93  	return eventValue, nil
    94  }
    95  
    96  func parseHeightFromEventKey(key []byte) (int64, error) {
    97  	var (
    98  		compositeKey, typ, eventValue string
    99  		height                        int64
   100  	)
   101  
   102  	_, err := orderedcode.Parse(string(key), &compositeKey, &eventValue, &height, &typ)
   103  	if err != nil {
   104  		return -1, fmt.Errorf("failed to parse event key: %w", err)
   105  	}
   106  
   107  	return height, nil
   108  }
   109  
   110  func parseEventSeqFromEventKey(key []byte) (int64, error) {
   111  	var (
   112  		compositeKey, typ, eventValue string
   113  		height                        int64
   114  		eventSeq                      int64
   115  	)
   116  
   117  	remaining, err := orderedcode.Parse(string(key), &compositeKey, &eventValue, &height, &typ)
   118  	if err != nil {
   119  		return 0, fmt.Errorf("failed to parse event key: %w", err)
   120  	}
   121  
   122  	// This is done to support previous versions that did not have event sequence in their key
   123  	if len(remaining) != 0 {
   124  		remaining, err = orderedcode.Parse(remaining, &eventSeq)
   125  		if err != nil {
   126  			return 0, fmt.Errorf("failed to parse event key: %w", err)
   127  		}
   128  		if len(remaining) != 0 {
   129  			return 0, fmt.Errorf("unexpected remainder in key: %s", remaining)
   130  		}
   131  	}
   132  
   133  	return eventSeq, nil
   134  }
   135  
   136  // Remove all occurrences of height equality queries except one. While we are traversing the conditions, check whether the only condition in
   137  // addition to match events is the height equality or height range query. At the same time, if we do have a height range condition
   138  // ignore the height equality condition. If a height equality exists, place the condition index in the query and the desired height
   139  // into the heightInfo struct
   140  func dedupHeight(conditions []query.Condition) (dedupConditions []query.Condition, heightInfo HeightInfo, found bool) {
   141  	heightInfo.heightEqIdx = -1
   142  	heightRangeExists := false
   143  	var heightCondition []query.Condition
   144  	heightInfo.onlyHeightEq = true
   145  	heightInfo.onlyHeightRange = true
   146  	for _, c := range conditions {
   147  		if c.CompositeKey == types.BlockHeightKey {
   148  			if c.Op == query.OpEqual {
   149  				if found || heightRangeExists {
   150  					continue
   151  				} else {
   152  					heightCondition = append(heightCondition, c)
   153  					heightInfo.height = c.Operand.(*big.Int).Int64() // As height is assumed to always be int64
   154  					found = true
   155  				}
   156  			} else {
   157  				heightInfo.onlyHeightEq = false
   158  				heightRangeExists = true
   159  				dedupConditions = append(dedupConditions, c)
   160  			}
   161  		} else {
   162  			heightInfo.onlyHeightRange = false
   163  			heightInfo.onlyHeightEq = false
   164  			dedupConditions = append(dedupConditions, c)
   165  		}
   166  	}
   167  	if !heightRangeExists && len(heightCondition) != 0 {
   168  		heightInfo.heightEqIdx = len(dedupConditions)
   169  		heightInfo.onlyHeightRange = false
   170  		dedupConditions = append(dedupConditions, heightCondition...)
   171  	} else {
   172  		// If we found a range make sure we set the hegiht idx to -1 as the height equality
   173  		// will be removed
   174  		heightInfo.heightEqIdx = -1
   175  		heightInfo.height = 0
   176  		heightInfo.onlyHeightEq = false
   177  		found = false
   178  	}
   179  	return dedupConditions, heightInfo, found
   180  }
   181  
   182  func checkHeightConditions(heightInfo HeightInfo, keyHeight int64) bool {
   183  	if heightInfo.heightRange.Key != "" {
   184  		if !checkBounds(heightInfo.heightRange, big.NewInt(keyHeight)) {
   185  			return false
   186  		}
   187  	} else {
   188  		if heightInfo.height != 0 && keyHeight != heightInfo.height {
   189  			return false
   190  		}
   191  	}
   192  	return true
   193  }
   194  
   195  //nolint:unused,deadcode
   196  func lookForHeight(conditions []query.Condition) (int64, bool, int) {
   197  	for i, c := range conditions {
   198  		if c.CompositeKey == types.BlockHeightKey && c.Op == query.OpEqual {
   199  			return c.Operand.(int64), true, i
   200  		}
   201  	}
   202  
   203  	return 0, false, -1
   204  }