github.com/Finschia/finschia-sdk@v0.49.1/store/internal/proofs/helpers.go (about)

     1  package proofs
     2  
     3  import (
     4  	"sort"
     5  
     6  	"github.com/Finschia/ostracon/libs/rand"
     7  	tmcrypto "github.com/tendermint/tendermint/proto/tendermint/crypto"
     8  
     9  	sdkmaps "github.com/Finschia/finschia-sdk/store/internal/maps"
    10  )
    11  
    12  // SimpleResult contains a merkle.SimpleProof along with all data needed to build the confio/proof
    13  type SimpleResult struct {
    14  	Key      []byte
    15  	Value    []byte
    16  	Proof    *tmcrypto.Proof
    17  	RootHash []byte
    18  }
    19  
    20  // GenerateRangeProof makes a tree of size and returns a range proof for one random element
    21  //
    22  // returns a range proof and the root hash of the tree
    23  func GenerateRangeProof(size int, loc Where) *SimpleResult {
    24  	data := BuildMap(size)
    25  	root, proofs, allkeys := sdkmaps.ProofsFromMap(data)
    26  
    27  	key := GetKey(allkeys, loc)
    28  	proof := proofs[key]
    29  
    30  	res := &SimpleResult{
    31  		Key:      []byte(key),
    32  		Value:    toValue(key),
    33  		Proof:    proof,
    34  		RootHash: root,
    35  	}
    36  	return res
    37  }
    38  
    39  // Where selects a location for a key - Left, Right, or Middle
    40  type Where int
    41  
    42  const (
    43  	Left Where = iota
    44  	Right
    45  	Middle
    46  )
    47  
    48  func SortedKeys(data map[string][]byte) []string {
    49  	keys := make([]string, len(data))
    50  	i := 0
    51  	for k := range data {
    52  		keys[i] = k
    53  		i++
    54  	}
    55  	sort.Strings(keys)
    56  	return keys
    57  }
    58  
    59  func CalcRoot(data map[string][]byte) []byte {
    60  	root, _, _ := sdkmaps.ProofsFromMap(data)
    61  	return root
    62  }
    63  
    64  // GetKey this returns a key, on Left/Right/Middle
    65  func GetKey(allkeys []string, loc Where) string {
    66  	if loc == Left {
    67  		return allkeys[0]
    68  	}
    69  	if loc == Right {
    70  		return allkeys[len(allkeys)-1]
    71  	}
    72  	// select a random index between 1 and allkeys-2
    73  	idx := rand.Int()%(len(allkeys)-2) + 1
    74  	return allkeys[idx]
    75  }
    76  
    77  // GetNonKey returns a missing key - Left of all, Right of all, or in the Middle
    78  func GetNonKey(allkeys []string, loc Where) string {
    79  	if loc == Left {
    80  		return string([]byte{1, 1, 1, 1})
    81  	}
    82  	if loc == Right {
    83  		return string([]byte{0xff, 0xff, 0xff, 0xff})
    84  	}
    85  	// otherwise, next to an existing key (copy before mod)
    86  	key := GetKey(allkeys, loc)
    87  	key = key[:len(key)-2] + string([]byte{255, 255})
    88  	return key
    89  }
    90  
    91  func toValue(key string) []byte {
    92  	return []byte("value_for_" + key)
    93  }
    94  
    95  // BuildMap creates random key/values and stores in a map,
    96  // returns a list of all keys in sorted order
    97  func BuildMap(size int) map[string][]byte {
    98  	data := make(map[string][]byte)
    99  	// insert lots of info and store the bytes
   100  	for i := 0; i < size; i++ {
   101  		key := rand.Str(20)
   102  		data[key] = toValue(key)
   103  	}
   104  	return data
   105  }