cosmos-sdk/store/internal/proofs/helpers.go

106 lines
2.4 KiB
Go

package proofs
import (
"sort"
"github.com/tendermint/tendermint/libs/rand"
tmcrypto "github.com/tendermint/tendermint/proto/tendermint/crypto"
sdkmaps "github.com/cosmos/cosmos-sdk/store/internal/maps"
)
// SimpleResult contains a merkle.SimpleProof along with all data needed to build the confio/proof
type SimpleResult struct {
Key []byte
Value []byte
Proof *tmcrypto.Proof
RootHash []byte
}
// GenerateRangeProof makes a tree of size and returns a range proof for one random element
//
// returns a range proof and the root hash of the tree
func GenerateRangeProof(size int, loc Where) *SimpleResult {
data := BuildMap(size)
root, proofs, allkeys := sdkmaps.ProofsFromMap(data)
key := GetKey(allkeys, loc)
proof := proofs[key]
res := &SimpleResult{
Key: []byte(key),
Value: toValue(key),
Proof: proof,
RootHash: root,
}
return res
}
// Where selects a location for a key - Left, Right, or Middle
type Where int
const (
Left Where = iota
Right
Middle
)
func SortedKeys(data map[string][]byte) []string {
keys := make([]string, len(data))
i := 0
for k := range data {
keys[i] = k
i++
}
sort.Strings(keys)
return keys
}
func CalcRoot(data map[string][]byte) []byte {
root, _, _ := sdkmaps.ProofsFromMap(data)
return root
}
// GetKey this returns a key, on Left/Right/Middle
func GetKey(allkeys []string, loc Where) string {
if loc == Left {
return allkeys[0]
}
if loc == Right {
return allkeys[len(allkeys)-1]
}
// select a random index between 1 and allkeys-2
idx := rand.Int()%(len(allkeys)-2) + 1
return allkeys[idx]
}
// GetNonKey returns a missing key - Left of all, Right of all, or in the Middle
func GetNonKey(allkeys []string, loc Where) string {
if loc == Left {
return string([]byte{1, 1, 1, 1})
}
if loc == Right {
return string([]byte{0xff, 0xff, 0xff, 0xff})
}
// otherwise, next to an existing key (copy before mod)
key := GetKey(allkeys, loc)
key = key[:len(key)-2] + string([]byte{255, 255})
return key
}
func toValue(key string) []byte {
return []byte("value_for_" + key)
}
// BuildMap creates random key/values and stores in a map,
// returns a list of all keys in sorted order
func BuildMap(size int) map[string][]byte {
data := make(map[string][]byte)
// insert lots of info and store the bytes
for i := 0; i < size; i++ {
key := rand.Str(20)
data[key] = toValue(key)
}
return data
}