github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/libs/cosmos-sdk/store/prefix/store.go (about) 1 package prefix 2 3 import ( 4 "bytes" 5 "errors" 6 "io" 7 8 "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/store/cachekv" 9 "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/store/tracekv" 10 "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/store/types" 11 ) 12 13 var _ types.KVStore = Store{} 14 15 // Store is similar with tendermint/tendermint/libs/db/prefix_db 16 // both gives access only to the limited subset of the store 17 // for convinience or safety 18 type Store struct { 19 parent types.KVStore 20 prefix []byte 21 } 22 23 func NewStore(parent types.KVStore, prefix []byte) Store { 24 return Store{ 25 parent: parent, 26 prefix: prefix, 27 } 28 } 29 30 func cloneAppend(bz []byte, tail []byte) (res []byte) { 31 res = make([]byte, len(bz)+len(tail)) 32 copy(res, bz) 33 copy(res[len(bz):], tail) 34 return 35 } 36 37 func (s Store) key(key []byte) (res []byte) { 38 if key == nil { 39 panic("nil key on Store") 40 } 41 res = cloneAppend(s.prefix, key) 42 return 43 } 44 45 // Implements Store 46 func (s Store) GetStoreType() types.StoreType { 47 return s.parent.GetStoreType() 48 } 49 50 // Implements CacheWrap 51 func (s Store) CacheWrap() types.CacheWrap { 52 return cachekv.NewStore(s) 53 } 54 55 // CacheWrapWithTrace implements the KVStore interface. 56 func (s Store) CacheWrapWithTrace(w io.Writer, tc types.TraceContext) types.CacheWrap { 57 return cachekv.NewStore(tracekv.NewStore(s, w, tc)) 58 } 59 60 // Implements KVStore 61 func (s Store) Get(key []byte) []byte { 62 res := s.parent.Get(s.key(key)) 63 return res 64 } 65 66 // Implements KVStore 67 func (s Store) Has(key []byte) bool { 68 return s.parent.Has(s.key(key)) 69 } 70 71 // Implements KVStore 72 func (s Store) Set(key, value []byte) { 73 types.AssertValidKey(key) 74 types.AssertValidValue(value) 75 s.parent.Set(s.key(key), value) 76 } 77 78 // Implements KVStore 79 func (s Store) Delete(key []byte) { 80 s.parent.Delete(s.key(key)) 81 } 82 83 // Implements KVStore 84 // Check https://github.com/tendermint/tendermint/blob/master/libs/db/prefix_db.go#L106 85 func (s Store) Iterator(start, end []byte) types.Iterator { 86 newstart := cloneAppend(s.prefix, start) 87 88 var newend []byte 89 if end == nil { 90 newend = cpIncr(s.prefix) 91 } else { 92 newend = cloneAppend(s.prefix, end) 93 } 94 95 iter := s.parent.Iterator(newstart, newend) 96 97 return newPrefixIterator(s.prefix, start, end, iter) 98 } 99 100 // Implements KVStore 101 // Check https://github.com/tendermint/tendermint/blob/master/libs/db/prefix_db.go#L129 102 func (s Store) ReverseIterator(start, end []byte) types.Iterator { 103 newstart := cloneAppend(s.prefix, start) 104 105 var newend []byte 106 if end == nil { 107 newend = cpIncr(s.prefix) 108 } else { 109 newend = cloneAppend(s.prefix, end) 110 } 111 112 iter := s.parent.ReverseIterator(newstart, newend) 113 114 return newPrefixIterator(s.prefix, start, end, iter) 115 } 116 117 var _ types.Iterator = (*prefixIterator)(nil) 118 119 type prefixIterator struct { 120 prefix []byte 121 start, end []byte 122 iter types.Iterator 123 valid bool 124 } 125 126 func newPrefixIterator(prefix, start, end []byte, parent types.Iterator) *prefixIterator { 127 return &prefixIterator{ 128 prefix: prefix, 129 start: start, 130 end: end, 131 iter: parent, 132 valid: parent.Valid() && bytes.HasPrefix(parent.Key(), prefix), 133 } 134 } 135 136 // Implements Iterator 137 func (iter *prefixIterator) Domain() ([]byte, []byte) { 138 return iter.start, iter.end 139 } 140 141 // Implements Iterator 142 func (iter *prefixIterator) Valid() bool { 143 return iter.valid && iter.iter.Valid() 144 } 145 146 // Implements Iterator 147 func (iter *prefixIterator) Next() { 148 if !iter.valid { 149 panic("prefixIterator invalid, cannot call Next()") 150 } 151 iter.iter.Next() 152 if !iter.iter.Valid() || !bytes.HasPrefix(iter.iter.Key(), iter.prefix) { 153 iter.valid = false 154 } 155 } 156 157 // Implements Iterator 158 func (iter *prefixIterator) Key() (key []byte) { 159 if !iter.valid { 160 panic("prefixIterator invalid, cannot call Key()") 161 } 162 key = iter.iter.Key() 163 key = stripPrefix(key, iter.prefix) 164 return 165 } 166 167 // Implements Iterator 168 func (iter *prefixIterator) Value() []byte { 169 if !iter.valid { 170 panic("prefixIterator invalid, cannot call Value()") 171 } 172 return iter.iter.Value() 173 } 174 175 // Implements Iterator 176 func (iter *prefixIterator) Close() { 177 iter.iter.Close() 178 } 179 180 // Error returns an error if the prefixIterator is invalid defined by the Valid 181 // method. 182 func (iter *prefixIterator) Error() error { 183 if !iter.Valid() { 184 return errors.New("invalid prefixIterator") 185 } 186 187 return nil 188 } 189 190 // copied from github.com/tendermint/tendermint/libs/db/prefix_db.go 191 func stripPrefix(key []byte, prefix []byte) []byte { 192 if len(key) < len(prefix) || !bytes.Equal(key[:len(prefix)], prefix) { 193 panic("should not happen") 194 } 195 return key[len(prefix):] 196 } 197 198 // wrapping types.PrefixEndBytes 199 func cpIncr(bz []byte) []byte { 200 return types.PrefixEndBytes(bz) 201 }