-
Notifications
You must be signed in to change notification settings - Fork 0
/
store_helper.go
139 lines (117 loc) · 4.08 KB
/
store_helper.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
package utils
import (
"errors"
"fmt"
sdk "github.com/cosmos/cosmos-sdk/types"
db "github.com/tendermint/tm-db"
"github.com/cosmos/cosmos-sdk/store"
"github.com/gogo/protobuf/proto"
)
func GatherAllKeysFromStore(storeObj store.KVStore) []string {
iterator := storeObj.Iterator(nil, nil)
defer iterator.Close()
keys := []string{}
for ; iterator.Valid(); iterator.Next() {
keys = append(keys, string(iterator.Key()))
}
return keys
}
func GatherValuesFromStore[T any](storeObj store.KVStore, keyStart []byte, keyEnd []byte, parseValue func([]byte) (T, error)) ([]T, error) {
iterator := storeObj.Iterator(keyStart, keyEnd)
defer iterator.Close()
return gatherValuesFromIteratorWithStop(iterator, parseValue, noStopFn)
}
func GatherValuesFromStorePrefix[T any](storeObj store.KVStore, prefix []byte, parseValue func([]byte) (T, error)) ([]T, error) {
iterator := sdk.KVStorePrefixIterator(storeObj, prefix)
defer iterator.Close()
return gatherValuesFromIteratorWithStop(iterator, parseValue, noStopFn)
}
func GetValuesUntilDerivedStop[T any](storeObj store.KVStore, keyStart []byte, stopFn func([]byte) bool, parseValue func([]byte) (T, error)) ([]T, error) {
// SDK iterator is broken for nil end time, and non-nil start time
// https://github.com/cosmos/cosmos-sdk/issues/12661
// hence we use []byte{0xff}
keyEnd := []byte{0xff}
return GetIterValuesWithStop(storeObj, keyStart, keyEnd, false, stopFn, parseValue)
}
func makeIterator(storeObj store.KVStore, keyStart []byte, keyEnd []byte, reverse bool) store.Iterator {
if reverse {
return storeObj.ReverseIterator(keyStart, keyEnd)
}
return storeObj.Iterator(keyStart, keyEnd)
}
func GetIterValuesWithStop[T any](
storeObj store.KVStore,
keyStart []byte,
keyEnd []byte,
reverse bool,
stopFn func([]byte) bool,
parseValue func([]byte) (T, error),
) ([]T, error) {
iter := makeIterator(storeObj, keyStart, keyEnd, reverse)
defer iter.Close()
return gatherValuesFromIteratorWithStop(iter, parseValue, stopFn)
}
func GetFirstValueAfterPrefixInclusive[T any](storeObj store.KVStore, keyStart []byte, parseValue func([]byte) (T, error)) (T, error) {
// SDK iterator is broken for nil end time, and non-nil start time
// https://github.com/cosmos/cosmos-sdk/issues/12661
// hence we use []byte{0xff}
return GetFirstValueInRange(storeObj, keyStart, []byte{0xff}, false, parseValue)
}
func GetFirstValueInRange[T any](storeObj store.KVStore, keyStart []byte, keyEnd []byte, reverseIterate bool, parseValue func([]byte) (T, error)) (T, error) {
iterator := makeIterator(storeObj, keyStart, keyEnd, reverseIterate)
defer iterator.Close()
if !iterator.Valid() {
var blankValue T
return blankValue, errors.New("no values in range")
}
return parseValue(iterator.Value())
}
func gatherValuesFromIteratorWithStop[T any](iterator db.Iterator, parseValue func([]byte) (T, error), stopFn func([]byte) bool) ([]T, error) {
values := []T{}
for ; iterator.Valid(); iterator.Next() {
if stopFn(iterator.Key()) {
break
}
val, err := parseValue(iterator.Value())
if err != nil {
return nil, err
}
values = append(values, val)
}
return values, nil
}
func noStopFn([]byte) bool {
return false
}
// MustSet runs store.Set(key, proto.Marshal(value))
// but panics on any error.
func MustSet(storeObj store.KVStore, key []byte, value proto.Message) {
bz, err := proto.Marshal(value)
if err != nil {
panic(err)
}
storeObj.Set(key, bz)
}
// MustGet gets key from store by mutating result
// Panics on any error.
func MustGet(store store.KVStore, key []byte, result proto.Message) {
b := store.Get(key)
if b == nil {
panic(fmt.Errorf("getting at key (%v) should not have been nil", key))
}
if err := proto.Unmarshal(b, result); err != nil {
panic(err)
}
}
// MustSetDec sets dec value to store at key. Panics on any error.
func MustSetDec(store store.KVStore, key []byte, value sdk.Dec) {
MustSet(store, key, &sdk.DecProto{
Dec: value,
})
}
// MustGetDec gets dec value from store at key. Panics on any error.
func MustGetDec(store store.KVStore, key []byte) sdk.Dec {
result := &sdk.DecProto{}
MustGet(store, key, result)
return result.Dec
}