2018-08-31 02:03:43 -07:00
|
|
|
package space
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"reflect"
|
|
|
|
|
|
|
|
tmlibs "github.com/tendermint/tendermint/libs/common"
|
|
|
|
|
|
|
|
"github.com/cosmos/cosmos-sdk/codec"
|
|
|
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
|
|
|
)
|
|
|
|
|
|
|
|
// Individual parameter store for each keeper
|
|
|
|
type Space struct {
|
|
|
|
cdc *codec.Codec
|
|
|
|
key sdk.StoreKey
|
|
|
|
tkey sdk.StoreKey
|
|
|
|
|
|
|
|
space []byte
|
|
|
|
}
|
|
|
|
|
|
|
|
// NewSpace constructs a store with namespace
|
|
|
|
func NewSpace(cdc *codec.Codec, key sdk.StoreKey, tkey sdk.StoreKey, space string) Space {
|
|
|
|
if !tmlibs.IsASCIIText(space) {
|
|
|
|
panic("paramstore space expressions can only contain alphanumeric characters")
|
|
|
|
}
|
|
|
|
|
|
|
|
return Space{
|
|
|
|
cdc: cdc,
|
|
|
|
key: key,
|
|
|
|
tkey: tkey,
|
|
|
|
|
2018-09-10 04:59:05 -07:00
|
|
|
space: append([]byte(space), '/'),
|
2018-08-31 02:03:43 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get parameter from store
|
2018-09-17 08:28:13 -07:00
|
|
|
func (s Space) Get(ctx sdk.Context, key string, ptr interface{}) {
|
2018-08-31 02:03:43 -07:00
|
|
|
store := ctx.KVStore(s.key).Prefix(s.space)
|
2018-09-17 08:28:13 -07:00
|
|
|
bz := store.Get([]byte(key))
|
2018-08-31 02:03:43 -07:00
|
|
|
err := s.cdc.UnmarshalJSON(bz, ptr)
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetIfExists do not modify ptr if the stored parameter is nil
|
2018-09-17 08:28:13 -07:00
|
|
|
func (s Space) GetIfExists(ctx sdk.Context, key string, ptr interface{}) {
|
2018-08-31 02:03:43 -07:00
|
|
|
store := ctx.KVStore(s.key).Prefix(s.space)
|
2018-09-17 08:28:13 -07:00
|
|
|
bz := store.Get([]byte(key))
|
2018-08-31 02:03:43 -07:00
|
|
|
if bz == nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
err := s.cdc.UnmarshalJSON(bz, ptr)
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get raw bytes of parameter from store
|
2018-09-17 08:28:13 -07:00
|
|
|
func (s Space) GetRaw(ctx sdk.Context, key string) []byte {
|
2018-08-31 02:03:43 -07:00
|
|
|
store := ctx.KVStore(s.key).Prefix(s.space)
|
2018-09-17 08:28:13 -07:00
|
|
|
res := store.Get([]byte(key))
|
2018-08-31 02:03:43 -07:00
|
|
|
return res
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check if the parameter is set in the store
|
2018-09-17 08:28:13 -07:00
|
|
|
func (s Space) Has(ctx sdk.Context, key string) bool {
|
2018-08-31 02:03:43 -07:00
|
|
|
store := ctx.KVStore(s.key).Prefix(s.space)
|
2018-09-17 08:28:13 -07:00
|
|
|
return store.Has([]byte(key))
|
2018-08-31 02:03:43 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// Returns true if the parameter is set in the block
|
2018-09-17 08:28:13 -07:00
|
|
|
func (s Space) Modified(ctx sdk.Context, key string) bool {
|
2018-08-31 02:03:43 -07:00
|
|
|
tstore := ctx.KVStore(s.tkey).Prefix(s.space)
|
2018-09-17 08:28:13 -07:00
|
|
|
return tstore.Has([]byte(key))
|
2018-08-31 02:03:43 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// Set parameter, return error if stored parameter has different type from input
|
2018-09-17 08:28:13 -07:00
|
|
|
func (s Space) Set(ctx sdk.Context, key string, param interface{}) {
|
2018-08-31 02:03:43 -07:00
|
|
|
store := ctx.KVStore(s.key).Prefix(s.space)
|
2018-09-17 08:28:13 -07:00
|
|
|
keybz := []byte(key)
|
2018-08-31 02:03:43 -07:00
|
|
|
|
|
|
|
bz := store.Get(keybz)
|
|
|
|
if bz != nil {
|
|
|
|
ptrty := reflect.PtrTo(reflect.TypeOf(param))
|
|
|
|
ptr := reflect.New(ptrty).Interface()
|
|
|
|
|
|
|
|
if s.cdc.UnmarshalJSON(bz, ptr) != nil {
|
2018-09-10 05:10:06 -07:00
|
|
|
panic(fmt.Errorf("Type mismatch with stored param and provided param"))
|
2018-08-31 02:03:43 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bz, err := s.cdc.MarshalJSON(param)
|
|
|
|
if err != nil {
|
2018-09-10 05:10:06 -07:00
|
|
|
panic(err)
|
2018-08-31 02:03:43 -07:00
|
|
|
}
|
|
|
|
store.Set(keybz, bz)
|
|
|
|
|
|
|
|
tstore := ctx.KVStore(s.tkey).Prefix(s.space)
|
|
|
|
tstore.Set(keybz, []byte{})
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set raw bytes of parameter
|
2018-09-17 08:28:13 -07:00
|
|
|
func (s Space) SetRaw(ctx sdk.Context, key string, param []byte) {
|
|
|
|
keybz := []byte(key)
|
2018-08-31 02:03:43 -07:00
|
|
|
|
|
|
|
store := ctx.KVStore(s.key).Prefix(s.space)
|
|
|
|
store.Set(keybz, param)
|
|
|
|
|
|
|
|
tstore := ctx.KVStore(s.tkey).Prefix(s.space)
|
|
|
|
tstore.Set(keybz, []byte{})
|
|
|
|
}
|
|
|
|
|
2018-09-17 08:28:13 -07:00
|
|
|
// Set from ParamStruct
|
|
|
|
func (s Space) SetFromParamStruct(ctx sdk.Context, ps ParamStruct) {
|
|
|
|
for _, pair := range ps.KeyFieldPairs() {
|
|
|
|
s.Set(ctx, pair.Key, pair.Field)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-08-31 02:03:43 -07:00
|
|
|
// Returns a KVStore identical with the paramspace
|
|
|
|
func (s Space) KVStore(ctx sdk.Context) sdk.KVStore {
|
|
|
|
return ctx.KVStore(s.key).Prefix(s.space)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Wrapper of Space, provides immutable functions only
|
|
|
|
type ReadOnlySpace struct {
|
|
|
|
s Space
|
|
|
|
}
|
|
|
|
|
|
|
|
// Exposes Get
|
2018-09-17 08:28:13 -07:00
|
|
|
func (ros ReadOnlySpace) Get(ctx sdk.Context, key string, ptr interface{}) {
|
2018-08-31 02:03:43 -07:00
|
|
|
ros.s.Get(ctx, key, ptr)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Exposes GetRaw
|
2018-09-17 08:28:13 -07:00
|
|
|
func (ros ReadOnlySpace) GetRaw(ctx sdk.Context, key string) []byte {
|
2018-08-31 02:03:43 -07:00
|
|
|
return ros.s.GetRaw(ctx, key)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Exposes Has
|
2018-09-17 08:28:13 -07:00
|
|
|
func (ros ReadOnlySpace) Has(ctx sdk.Context, key string) bool {
|
2018-08-31 02:03:43 -07:00
|
|
|
return ros.s.Has(ctx, key)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Exposes Modified
|
2018-09-17 08:28:13 -07:00
|
|
|
func (ros ReadOnlySpace) Modified(ctx sdk.Context, key string) bool {
|
2018-08-31 02:03:43 -07:00
|
|
|
return ros.s.Modified(ctx, key)
|
|
|
|
}
|