github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/libs/cosmos-sdk/store/gaskv/store.go (about)

     1  package gaskv
     2  
     3  import (
     4  	"io"
     5  
     6  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/store/types"
     7  )
     8  
     9  var _ types.KVStore = &Store{}
    10  
    11  // Store applies gas tracking to an underlying KVStore. It implements the
    12  // KVStore interface.
    13  type Store struct {
    14  	gasMeter  types.GasMeter
    15  	gasConfig types.GasConfig
    16  	parent    types.KVStore
    17  }
    18  
    19  // NewStore returns a reference to a new GasKVStore.
    20  // nolint
    21  func NewStore(parent types.KVStore, gasMeter types.GasMeter, gasConfig types.GasConfig) *Store {
    22  	kvs := &Store{
    23  		gasMeter:  gasMeter,
    24  		gasConfig: gasConfig,
    25  		parent:    parent,
    26  	}
    27  	return kvs
    28  }
    29  
    30  func ResetStore(kvs *Store, parent types.KVStore, gasMeter types.GasMeter, gasConfig types.GasConfig) *Store {
    31  	*kvs = Store{
    32  		gasMeter:  gasMeter,
    33  		gasConfig: gasConfig,
    34  		parent:    parent,
    35  	}
    36  	return kvs
    37  }
    38  
    39  // Implements Store.
    40  func (gs *Store) GetStoreType() types.StoreType {
    41  	return gs.parent.GetStoreType()
    42  }
    43  
    44  // Implements KVStore.
    45  func (gs *Store) Get(key []byte) (value []byte) {
    46  	gs.gasMeter.ConsumeGas(gs.gasConfig.ReadCostFlat, types.GasReadCostFlatDesc)
    47  	value = gs.parent.Get(key)
    48  
    49  	// TODO overflow-safe math?
    50  	gs.gasMeter.ConsumeGas(gs.gasConfig.ReadCostPerByte*types.Gas(len(value)), types.GasReadPerByteDesc)
    51  
    52  	return value
    53  }
    54  
    55  // Implements KVStore.
    56  func (gs *Store) Set(key []byte, value []byte) {
    57  	types.AssertValidValue(value)
    58  	gs.gasMeter.ConsumeGas(gs.gasConfig.WriteCostFlat, types.GasWriteCostFlatDesc)
    59  	// TODO overflow-safe math?
    60  	gs.gasMeter.ConsumeGas(gs.gasConfig.WriteCostPerByte*types.Gas(len(value)), types.GasWritePerByteDesc)
    61  	gs.parent.Set(key, value)
    62  }
    63  
    64  // Implements KVStore.
    65  func (gs *Store) Has(key []byte) bool {
    66  	gs.gasMeter.ConsumeGas(gs.gasConfig.HasCost, types.GasHasDesc)
    67  	return gs.parent.Has(key)
    68  }
    69  
    70  // Implements KVStore.
    71  func (gs *Store) Delete(key []byte) {
    72  	// charge gas to prevent certain attack vectors even though space is being freed
    73  	gs.gasMeter.ConsumeGas(gs.gasConfig.DeleteCost, types.GasDeleteDesc)
    74  	gs.parent.Delete(key)
    75  }
    76  
    77  // Iterator implements the KVStore interface. It returns an iterator which
    78  // incurs a flat gas cost for seeking to the first key/value pair and a variable
    79  // gas cost based on the current value's length if the iterator is valid.
    80  func (gs *Store) Iterator(start, end []byte) types.Iterator {
    81  	return gs.iterator(start, end, true)
    82  }
    83  
    84  // ReverseIterator implements the KVStore interface. It returns a reverse
    85  // iterator which incurs a flat gas cost for seeking to the first key/value pair
    86  // and a variable gas cost based on the current value's length if the iterator
    87  // is valid.
    88  func (gs *Store) ReverseIterator(start, end []byte) types.Iterator {
    89  	return gs.iterator(start, end, false)
    90  }
    91  
    92  // Implements KVStore.
    93  func (gs *Store) CacheWrap() types.CacheWrap {
    94  	panic("cannot CacheWrap a GasKVStore")
    95  }
    96  
    97  // CacheWrapWithTrace implements the KVStore interface.
    98  func (gs *Store) CacheWrapWithTrace(_ io.Writer, _ types.TraceContext) types.CacheWrap {
    99  	panic("cannot CacheWrapWithTrace a GasKVStore")
   100  }
   101  
   102  func (gs *Store) iterator(start, end []byte, ascending bool) types.Iterator {
   103  	var parent types.Iterator
   104  	if ascending {
   105  		parent = gs.parent.Iterator(start, end)
   106  	} else {
   107  		parent = gs.parent.ReverseIterator(start, end)
   108  	}
   109  
   110  	gi := newGasIterator(gs.gasMeter, gs.gasConfig, parent)
   111  	if gi.Valid() {
   112  		gi.(*gasIterator).consumeSeekGas()
   113  	}
   114  
   115  	return gi
   116  }
   117  
   118  type gasIterator struct {
   119  	gasMeter  types.GasMeter
   120  	gasConfig types.GasConfig
   121  	parent    types.Iterator
   122  }
   123  
   124  func newGasIterator(gasMeter types.GasMeter, gasConfig types.GasConfig, parent types.Iterator) types.Iterator {
   125  	return &gasIterator{
   126  		gasMeter:  gasMeter,
   127  		gasConfig: gasConfig,
   128  		parent:    parent,
   129  	}
   130  }
   131  
   132  // Implements Iterator.
   133  func (gi *gasIterator) Domain() (start []byte, end []byte) {
   134  	return gi.parent.Domain()
   135  }
   136  
   137  // Implements Iterator.
   138  func (gi *gasIterator) Valid() bool {
   139  	return gi.parent.Valid()
   140  }
   141  
   142  // Next implements the Iterator interface. It seeks to the next key/value pair
   143  // in the iterator. It incurs a flat gas cost for seeking and a variable gas
   144  // cost based on the current value's length if the iterator is valid.
   145  func (gi *gasIterator) Next() {
   146  	if gi.Valid() {
   147  		gi.consumeSeekGas()
   148  	}
   149  
   150  	gi.parent.Next()
   151  }
   152  
   153  // Key implements the Iterator interface. It returns the current key and it does
   154  // not incur any gas cost.
   155  func (gi *gasIterator) Key() (key []byte) {
   156  	key = gi.parent.Key()
   157  	return key
   158  }
   159  
   160  // Value implements the Iterator interface. It returns the current value and it
   161  // does not incur any gas cost.
   162  func (gi *gasIterator) Value() (value []byte) {
   163  	value = gi.parent.Value()
   164  	return value
   165  }
   166  
   167  // Implements Iterator.
   168  func (gi *gasIterator) Close() {
   169  	gi.parent.Close()
   170  }
   171  
   172  // Error delegates the Error call to the parent iterator.
   173  func (gi *gasIterator) Error() error {
   174  	return gi.parent.Error()
   175  }
   176  
   177  // consumeSeekGas consumes a flat gas cost for seeking and a variable gas cost
   178  // based on the current value's length.
   179  func (gi *gasIterator) consumeSeekGas() {
   180  	value := gi.Value()
   181  
   182  	gi.gasMeter.ConsumeGas(gi.gasConfig.ReadCostPerByte*types.Gas(len(value)), types.GasValuePerByteDesc)
   183  	gi.gasMeter.ConsumeGas(gi.gasConfig.IterNextCostFlat, types.GasIterNextCostFlatDesc)
   184  
   185  }