2017-12-21 20:05:41 -08:00
|
|
|
package types
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
2018-07-12 16:58:51 -07:00
|
|
|
"io"
|
2017-12-21 20:05:41 -08:00
|
|
|
|
2018-06-28 17:54:47 -07:00
|
|
|
abci "github.com/tendermint/tendermint/abci/types"
|
2018-07-02 13:34:06 -07:00
|
|
|
cmn "github.com/tendermint/tendermint/libs/common"
|
|
|
|
dbm "github.com/tendermint/tendermint/libs/db"
|
2017-12-21 20:05:41 -08:00
|
|
|
)
|
|
|
|
|
|
|
|
// NOTE: These are implemented in cosmos-sdk/store.
|
|
|
|
|
2018-07-12 18:20:26 -07:00
|
|
|
// PruningStrategy specfies how old states will be deleted over time
|
|
|
|
type PruningStrategy uint8
|
|
|
|
|
|
|
|
const (
|
|
|
|
// PruneSyncable means only those states not needed for state syncing will be deleted (keeps last 100 + every 10000th)
|
|
|
|
PruneSyncable PruningStrategy = iota
|
|
|
|
|
|
|
|
// PruneEverything means all saved states will be deleted, storing only the current state
|
|
|
|
PruneEverything PruningStrategy = iota
|
|
|
|
|
|
|
|
// PruneNothing means all historic states will be saved, nothing will be deleted
|
|
|
|
PruneNothing PruningStrategy = iota
|
|
|
|
)
|
|
|
|
|
2018-02-04 16:59:11 -08:00
|
|
|
type Store interface { //nolint
|
2018-01-22 05:44:24 -08:00
|
|
|
GetStoreType() StoreType
|
|
|
|
CacheWrapper
|
|
|
|
}
|
|
|
|
|
2018-02-04 16:59:11 -08:00
|
|
|
// something that can persist to disk
|
2018-01-22 05:44:24 -08:00
|
|
|
type Committer interface {
|
|
|
|
Commit() CommitID
|
|
|
|
LastCommitID() CommitID
|
2018-07-12 18:20:26 -07:00
|
|
|
SetPruning(PruningStrategy)
|
2018-01-22 05:44:24 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Stores of MultiStore must implement CommitStore.
|
|
|
|
type CommitStore interface {
|
|
|
|
Committer
|
|
|
|
Store
|
|
|
|
}
|
|
|
|
|
2018-01-30 06:20:38 -08:00
|
|
|
// Queryable allows a Store to expose internal state to the abci.Query
|
|
|
|
// interface. Multistore can route requests to the proper Store.
|
|
|
|
//
|
|
|
|
// This is an optional, but useful extension to any CommitStore
|
|
|
|
type Queryable interface {
|
|
|
|
Query(abci.RequestQuery) abci.ResponseQuery
|
|
|
|
}
|
|
|
|
|
2017-12-21 20:05:41 -08:00
|
|
|
//----------------------------------------
|
|
|
|
// MultiStore
|
|
|
|
|
2018-02-04 16:59:11 -08:00
|
|
|
type MultiStore interface { //nolint
|
2018-01-22 05:44:24 -08:00
|
|
|
Store
|
2017-12-21 20:05:41 -08:00
|
|
|
|
|
|
|
// Cache wrap MultiStore.
|
|
|
|
// NOTE: Caller should probably not call .Write() on each, but
|
|
|
|
// call CacheMultiStore.Write().
|
|
|
|
CacheMultiStore() CacheMultiStore
|
|
|
|
|
2017-12-26 17:04:48 -08:00
|
|
|
// Convenience for fetching substores.
|
2018-01-22 05:44:24 -08:00
|
|
|
GetStore(StoreKey) Store
|
|
|
|
GetKVStore(StoreKey) KVStore
|
2018-07-12 16:58:51 -07:00
|
|
|
|
|
|
|
// TracingEnabled returns if tracing is enabled for the MultiStore.
|
|
|
|
TracingEnabled() bool
|
|
|
|
|
|
|
|
// WithTracer sets the tracer for the MultiStore that the underlying
|
|
|
|
// stores will utilize to trace operations. A MultiStore is returned.
|
|
|
|
WithTracer(w io.Writer) MultiStore
|
|
|
|
|
|
|
|
// WithTracingContext sets the tracing context for a MultiStore. It is
|
|
|
|
// implied that the caller should update the context when necessary between
|
|
|
|
// tracing operations. A MultiStore is returned.
|
|
|
|
WithTracingContext(TraceContext) MultiStore
|
|
|
|
|
|
|
|
// ResetTraceContext resets the current tracing context.
|
|
|
|
ResetTraceContext() MultiStore
|
2017-12-21 20:05:41 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
// From MultiStore.CacheMultiStore()....
|
|
|
|
type CacheMultiStore interface {
|
|
|
|
MultiStore
|
|
|
|
Write() // Writes operations to underlying KVStore
|
|
|
|
}
|
|
|
|
|
|
|
|
// A non-cache MultiStore.
|
|
|
|
type CommitMultiStore interface {
|
2018-01-22 05:44:24 -08:00
|
|
|
Committer
|
2017-12-21 20:05:41 -08:00
|
|
|
MultiStore
|
|
|
|
|
2018-02-16 16:52:07 -08:00
|
|
|
// Mount a store of type using the given db.
|
|
|
|
// If db == nil, the new store will use the CommitMultiStore db.
|
2018-01-22 05:44:24 -08:00
|
|
|
MountStoreWithDB(key StoreKey, typ StoreType, db dbm.DB)
|
2017-12-21 20:05:41 -08:00
|
|
|
|
2018-01-17 16:59:40 -08:00
|
|
|
// Panics on a nil key.
|
2018-01-22 05:44:24 -08:00
|
|
|
GetCommitStore(key StoreKey) CommitStore
|
2017-12-26 17:04:48 -08:00
|
|
|
|
2018-01-31 19:15:32 -08:00
|
|
|
// Panics on a nil key.
|
|
|
|
GetCommitKVStore(key StoreKey) CommitKVStore
|
|
|
|
|
2018-01-22 05:44:24 -08:00
|
|
|
// Load the latest persisted version. Called once after all
|
|
|
|
// calls to Mount*Store() are complete.
|
2017-12-21 20:05:41 -08:00
|
|
|
LoadLatestVersion() error
|
|
|
|
|
2018-01-22 05:44:24 -08:00
|
|
|
// Load a specific persisted version. When you load an old
|
|
|
|
// version, or when the last commit attempt didn't complete,
|
|
|
|
// the next commit after loading must be idempotent (return the
|
|
|
|
// same commit id). Otherwise the behavior is undefined.
|
2017-12-21 20:05:41 -08:00
|
|
|
LoadVersion(ver int64) error
|
|
|
|
}
|
|
|
|
|
2018-05-26 18:00:39 -07:00
|
|
|
//---------subsp-------------------------------
|
2017-12-21 20:05:41 -08:00
|
|
|
// KVStore
|
|
|
|
|
|
|
|
// KVStore is a simple interface to get/set data
|
|
|
|
type KVStore interface {
|
2018-01-22 05:44:24 -08:00
|
|
|
Store
|
2017-12-21 20:05:41 -08:00
|
|
|
|
|
|
|
// Get returns nil iff key doesn't exist. Panics on nil key.
|
|
|
|
Get(key []byte) []byte
|
|
|
|
|
|
|
|
// Has checks if a key exists. Panics on nil key.
|
|
|
|
Has(key []byte) bool
|
|
|
|
|
|
|
|
// Set sets the key. Panics on nil key.
|
|
|
|
Set(key, value []byte)
|
|
|
|
|
|
|
|
// Delete deletes the key. Panics on nil key.
|
|
|
|
Delete(key []byte)
|
|
|
|
|
|
|
|
// Iterator over a domain of keys in ascending order. End is exclusive.
|
|
|
|
// Start must be less than end, or the Iterator is invalid.
|
2018-06-16 17:45:48 -07:00
|
|
|
// Iterator must be closed by caller.
|
|
|
|
// To iterate over entire domain, use store.Iterator(nil, nil)
|
|
|
|
// CONTRACT: No writes may happen within a domain while an iterator exists over it.
|
2017-12-21 20:05:41 -08:00
|
|
|
Iterator(start, end []byte) Iterator
|
|
|
|
|
|
|
|
// Iterator over a domain of keys in descending order. End is exclusive.
|
|
|
|
// Start must be greater than end, or the Iterator is invalid.
|
2018-06-16 17:45:48 -07:00
|
|
|
// Iterator must be closed by caller.
|
|
|
|
// CONTRACT: No writes may happen within a domain while an iterator exists over it.
|
2017-12-21 20:05:41 -08:00
|
|
|
ReverseIterator(start, end []byte) Iterator
|
2018-01-12 11:49:53 -08:00
|
|
|
|
|
|
|
// TODO Not yet implemented.
|
|
|
|
// CreateSubKVStore(key *storeKey) (KVStore, error)
|
|
|
|
|
|
|
|
// TODO Not yet implemented.
|
|
|
|
// GetSubKVStore(key *storeKey) KVStore
|
2018-07-26 18:24:18 -07:00
|
|
|
|
|
|
|
// Prefix applied keys with the argument
|
|
|
|
// CONTRACT: when Prefix is called on a KVStore more than once,
|
|
|
|
// the concatanation of the prefixes is applied
|
|
|
|
Prefix(prefix []byte) KVStore
|
|
|
|
|
|
|
|
// Gas consuming store
|
|
|
|
// CONTRACT: when Gas is called on a KVStore more than once,
|
|
|
|
// the concatanation of the meters/configs is applied
|
|
|
|
Gas(GasMeter, GasConfig) KVStore
|
2017-12-21 20:05:41 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Alias iterator to db's Iterator for convenience.
|
|
|
|
type Iterator = dbm.Iterator
|
|
|
|
|
2018-05-26 18:00:39 -07:00
|
|
|
// Iterator over all the keys with a certain prefix in ascending order
|
|
|
|
func KVStorePrefixIterator(kvs KVStore, prefix []byte) Iterator {
|
|
|
|
return kvs.Iterator(prefix, PrefixEndBytes(prefix))
|
|
|
|
}
|
|
|
|
|
|
|
|
// Iterator over all the keys with a certain prefix in descending order.
|
|
|
|
func KVStoreReversePrefixIterator(kvs KVStore, prefix []byte) Iterator {
|
|
|
|
return kvs.ReverseIterator(prefix, PrefixEndBytes(prefix))
|
|
|
|
}
|
|
|
|
|
2018-01-22 05:44:24 -08:00
|
|
|
// CacheKVStore cache-wraps a KVStore. After calling .Write() on
|
|
|
|
// the CacheKVStore, all previously created CacheKVStores on the
|
|
|
|
// object expire.
|
2017-12-21 20:05:41 -08:00
|
|
|
type CacheKVStore interface {
|
|
|
|
KVStore
|
2018-01-22 05:44:24 -08:00
|
|
|
|
|
|
|
// Writes operations to underlying KVStore
|
|
|
|
Write()
|
2017-12-21 20:05:41 -08:00
|
|
|
}
|
|
|
|
|
2018-01-31 19:15:32 -08:00
|
|
|
// Stores of MultiStore must implement CommitStore.
|
|
|
|
type CommitKVStore interface {
|
|
|
|
Committer
|
|
|
|
KVStore
|
|
|
|
}
|
|
|
|
|
2017-12-21 20:05:41 -08:00
|
|
|
//----------------------------------------
|
|
|
|
// CacheWrap
|
|
|
|
|
2018-07-12 16:58:51 -07:00
|
|
|
// CacheWrap makes the most appropriate cache-wrap. For example,
|
|
|
|
// IAVLStore.CacheWrap() returns a CacheKVStore. CacheWrap should not return
|
|
|
|
// a Committer, since Commit cache-wraps make no sense. It can return KVStore,
|
|
|
|
// HeapStore, SpaceStore, etc.
|
2017-12-21 20:05:41 -08:00
|
|
|
type CacheWrap interface {
|
|
|
|
// Write syncs with the underlying store.
|
|
|
|
Write()
|
|
|
|
|
|
|
|
// CacheWrap recursively wraps again.
|
|
|
|
CacheWrap() CacheWrap
|
2018-07-12 16:58:51 -07:00
|
|
|
|
|
|
|
// CacheWrapWithTrace recursively wraps again with tracing enabled.
|
|
|
|
CacheWrapWithTrace(w io.Writer, tc TraceContext) CacheWrap
|
2017-12-21 20:05:41 -08:00
|
|
|
}
|
|
|
|
|
2018-02-04 16:59:11 -08:00
|
|
|
type CacheWrapper interface { //nolint
|
2018-07-12 16:58:51 -07:00
|
|
|
// CacheWrap cache wraps.
|
2018-02-04 16:59:11 -08:00
|
|
|
CacheWrap() CacheWrap
|
2018-07-12 16:58:51 -07:00
|
|
|
|
|
|
|
// CacheWrapWithTrace cache wraps with tracing enabled.
|
|
|
|
CacheWrapWithTrace(w io.Writer, tc TraceContext) CacheWrap
|
2018-02-04 16:59:11 -08:00
|
|
|
}
|
|
|
|
|
2017-12-21 20:05:41 -08:00
|
|
|
//----------------------------------------
|
2018-01-12 13:48:54 -08:00
|
|
|
// CommitID
|
2017-12-21 20:05:41 -08:00
|
|
|
|
|
|
|
// CommitID contains the tree version number and its merkle root.
|
|
|
|
type CommitID struct {
|
|
|
|
Version int64
|
|
|
|
Hash []byte
|
|
|
|
}
|
|
|
|
|
2018-02-04 16:59:11 -08:00
|
|
|
func (cid CommitID) IsZero() bool { //nolint
|
2017-12-21 20:05:41 -08:00
|
|
|
return cid.Version == 0 && len(cid.Hash) == 0
|
|
|
|
}
|
|
|
|
|
|
|
|
func (cid CommitID) String() string {
|
|
|
|
return fmt.Sprintf("CommitID{%v:%X}", cid.Hash, cid.Version)
|
|
|
|
}
|
2018-01-12 11:49:53 -08:00
|
|
|
|
2018-01-22 05:44:24 -08:00
|
|
|
//----------------------------------------
|
|
|
|
// Store types
|
|
|
|
|
2018-02-04 16:59:11 -08:00
|
|
|
// kind of store
|
2018-01-22 05:44:24 -08:00
|
|
|
type StoreType int
|
|
|
|
|
|
|
|
const (
|
2018-02-04 16:59:11 -08:00
|
|
|
//nolint
|
2018-01-22 05:44:24 -08:00
|
|
|
StoreTypeMulti StoreType = iota
|
|
|
|
StoreTypeDB
|
|
|
|
StoreTypeIAVL
|
2018-07-26 18:24:18 -07:00
|
|
|
StoreTypeTransient
|
2018-01-22 05:44:24 -08:00
|
|
|
)
|
|
|
|
|
2018-01-12 13:48:54 -08:00
|
|
|
//----------------------------------------
|
|
|
|
// Keys for accessing substores
|
|
|
|
|
2018-01-22 05:44:24 -08:00
|
|
|
// StoreKey is a key used to index stores in a MultiStore.
|
|
|
|
type StoreKey interface {
|
2018-01-12 13:48:54 -08:00
|
|
|
Name() string
|
|
|
|
String() string
|
|
|
|
}
|
|
|
|
|
|
|
|
// KVStoreKey is used for accessing substores.
|
|
|
|
// Only the pointer value should ever be used - it functions as a capabilities key.
|
|
|
|
type KVStoreKey struct {
|
|
|
|
name string
|
|
|
|
}
|
|
|
|
|
|
|
|
// NewKVStoreKey returns a new pointer to a KVStoreKey.
|
|
|
|
// Use a pointer so keys don't collide.
|
|
|
|
func NewKVStoreKey(name string) *KVStoreKey {
|
|
|
|
return &KVStoreKey{
|
|
|
|
name: name,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (key *KVStoreKey) Name() string {
|
|
|
|
return key.name
|
|
|
|
}
|
|
|
|
|
|
|
|
func (key *KVStoreKey) String() string {
|
|
|
|
return fmt.Sprintf("KVStoreKey{%p, %s}", key, key.name)
|
|
|
|
}
|
2018-04-01 09:00:28 -07:00
|
|
|
|
2018-04-06 02:29:25 -07:00
|
|
|
// PrefixEndBytes returns the []byte that would end a
|
|
|
|
// range query for all []byte with a certain prefix
|
|
|
|
// Deals with last byte of prefix being FF without overflowing
|
2018-04-01 09:00:28 -07:00
|
|
|
func PrefixEndBytes(prefix []byte) []byte {
|
|
|
|
if prefix == nil {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
end := make([]byte, len(prefix))
|
|
|
|
copy(end, prefix)
|
|
|
|
|
2018-04-06 02:29:25 -07:00
|
|
|
for {
|
2018-04-01 09:00:28 -07:00
|
|
|
if end[len(end)-1] != byte(255) {
|
|
|
|
end[len(end)-1]++
|
2018-04-06 02:29:25 -07:00
|
|
|
break
|
2018-04-01 09:00:28 -07:00
|
|
|
} else {
|
|
|
|
end = end[:len(end)-1]
|
|
|
|
if len(end) == 0 {
|
|
|
|
end = nil
|
2018-04-06 02:29:25 -07:00
|
|
|
break
|
2018-04-01 09:00:28 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return end
|
|
|
|
}
|
2018-05-08 09:47:31 -07:00
|
|
|
|
2018-07-26 18:24:18 -07:00
|
|
|
// TransientStoreKey is used for indexing transient stores in a MultiStore
|
|
|
|
type TransientStoreKey struct {
|
|
|
|
name string
|
|
|
|
}
|
|
|
|
|
|
|
|
// Constructs new TransientStoreKey
|
|
|
|
// Must return a pointer according to the ocap principle
|
|
|
|
func NewTransientStoreKey(name string) *TransientStoreKey {
|
|
|
|
return &TransientStoreKey{
|
|
|
|
name: name,
|
|
|
|
}
|
2018-06-21 14:33:36 -07:00
|
|
|
}
|
|
|
|
|
2018-07-26 18:24:18 -07:00
|
|
|
// Implements StoreKey
|
|
|
|
func (key *TransientStoreKey) Name() string {
|
|
|
|
return key.name
|
2018-06-21 14:33:36 -07:00
|
|
|
}
|
|
|
|
|
2018-07-26 18:24:18 -07:00
|
|
|
// Implements StoreKey
|
|
|
|
func (key *TransientStoreKey) String() string {
|
|
|
|
return fmt.Sprintf("TransientStoreKey{%p, %s}", key, key.name)
|
2018-06-21 14:33:36 -07:00
|
|
|
}
|
|
|
|
|
2018-05-08 09:47:31 -07:00
|
|
|
//----------------------------------------
|
|
|
|
|
|
|
|
// key-value result for iterator queries
|
2018-05-09 15:24:51 -07:00
|
|
|
type KVPair cmn.KVPair
|
2018-06-21 14:33:36 -07:00
|
|
|
|
|
|
|
//----------------------------------------
|
2018-07-12 16:58:51 -07:00
|
|
|
|
|
|
|
// TraceContext contains TraceKVStore context data. It will be written with
|
|
|
|
// every trace operation.
|
|
|
|
type TraceContext map[string]interface{}
|