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  }