Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

R4R: Store Accessor Types #4514

Closed
wants to merge 43 commits into from
Closed
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
9375649
add mapping
mossid Jun 7, 2019
16eea68
rm unused mapping/*, rm interfaces
mossid Jun 11, 2019
f73215e
rm unused code
mossid Jun 11, 2019
cf0b8f2
mv mapping -> state, rm x/ibc
mossid Jun 11, 2019
e25f652
Merge branch 'master' of github.com:cosmos/cosmos-sdk into joon/store…
mossid Jun 17, 2019
2b17a39
rm GetIfExists
mossid Jun 25, 2019
dc84e1e
add key
mossid Jun 25, 2019
19d7155
rm custom encoding/decoding in enum/bool
mossid Jun 26, 2019
6764bc4
Merge branch 'master' of github.com:cosmos/cosmos-sdk into joon/store…
mossid Jun 29, 2019
8affaa7
fix lint
mossid Jun 29, 2019
a7898b4
rm tests
mossid Jul 7, 2019
3939bd4
Merge branch 'master' of github.com:cosmos/cosmos-sdk into joon/store…
mossid Jul 9, 2019
f609249
add docs in progre
mossid Jul 24, 2019
7da69c1
add comments
mossid Jul 25, 2019
600445a
add comments
mossid Jul 25, 2019
94e2cdc
Merge branch 'master' of github.com:cosmos/cosmos-sdk into joon/store…
mossid Jul 26, 2019
8d9e779
add comments
mossid Jul 26, 2019
92d0fb4
fix comment
mossid Jul 26, 2019
5d913b7
recover IntEncoding scheme for integer
mossid Jul 29, 2019
699b0ba
add uint tests, don't use codec in custom types
mossid Jul 29, 2019
97edd89
Merge branch 'master' of github.com:cosmos/cosmos-sdk into joon/store…
mossid Jul 30, 2019
24e621a
add query
mossid Jul 31, 2019
971a642
update query.go
mossid Jul 31, 2019
fcad487
add Query to boolean.go
mossid Aug 1, 2019
6de0ed5
fix key
mossid Aug 1, 2019
6dc912f
godoc cleanup
alexanderbez Aug 7, 2019
63c6f3c
godoc cleanup
alexanderbez Aug 7, 2019
b6441c0
godoc cleanup
alexanderbez Aug 7, 2019
4d723ae
godoc cleanup
alexanderbez Aug 7, 2019
244d2c2
godoc cleanup
alexanderbez Aug 7, 2019
7bf4d57
merge from ics04 branch
mossid Aug 15, 2019
7471bdf
Merge branch 'joon/store-mapping' of github.com:cosmos/cosmos-sdk int…
mossid Aug 15, 2019
04543f8
Merge branch 'master' of github.com:cosmos/cosmos-sdk into joon/store…
mossid Sep 2, 2019
10d1c46
Apply suggestions from code review
mossid Sep 10, 2019
09e6600
applying review in progress
mossid Sep 11, 2019
6f5f633
Merge branch 'joon/store-mapping' of github.com:cosmos/cosmos-sdk int…
mossid Sep 11, 2019
4116bb7
apply review - make querier interface
mossid Sep 11, 2019
8040c81
Merge branch 'master' of github.com:cosmos/cosmos-sdk into joon/store…
mossid Sep 17, 2019
828badd
revise querier interface to work both on cli & store
mossid Sep 18, 2019
21bd8d0
Store accessor upstream changes (#5119)
fedekunze Oct 1, 2019
9b3b120
Merge branch 'master' into joon/store-mapping
fedekunze Oct 1, 2019
abd9fec
Apply suggestions from code review
mossid Oct 1, 2019
a6dadef
Merge branch 'master' into joon/store-mapping
fedekunze Oct 4, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 54 additions & 0 deletions store/state/base.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package state

import (
alexanderbez marked this conversation as resolved.
Show resolved Hide resolved
// "github.com/tendermint/tendermint/crypto/merkle"

"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/store/prefix"
sdk "github.com/cosmos/cosmos-sdk/types"
)

type Base struct {
fedekunze marked this conversation as resolved.
Show resolved Hide resolved
cdc *codec.Codec
storefn func(Context) KVStore
prefix []byte
}

func EmptyBase() Base {
return NewBase(nil, nil)
}

func NewBase(cdc *codec.Codec, key sdk.StoreKey) Base {
return Base{
cdc: cdc,
storefn: func(ctx Context) KVStore { return ctx.KVStore(key) },
}
}

func (base Base) store(ctx Context) KVStore {
return prefix.NewStore(base.storefn(ctx), base.prefix)
}

func join(a, b []byte) (res []byte) {
res = make([]byte, len(a)+len(b))
copy(res, a)
copy(res[len(a):], b)
return
}

func (base Base) Prefix(prefix []byte) (res Base) {
res = Base{
cdc: base.cdc,
storefn: base.storefn,
prefix: join(base.prefix, prefix),
}
return
}

func (base Base) Cdc() *codec.Codec {
return base.cdc
}

func (base Base) key(key []byte) []byte {
return join(base.prefix, key)
}
23 changes: 23 additions & 0 deletions store/state/boolean.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package state

type Boolean struct {
alexanderbez marked this conversation as resolved.
Show resolved Hide resolved
Value
}

func NewBoolean(v Value) Boolean {
return Boolean{v}
}

func (v Boolean) Get(ctx Context) (res bool) {
v.Value.Get(ctx, &res)
return
}

func (v Boolean) GetSafe(ctx Context) (res bool, err error) {
err = v.Value.GetSafe(ctx, &res)
return
}

func (v Boolean) Set(ctx Context, value bool) {
v.Value.Set(ctx, value)
}
37 changes: 37 additions & 0 deletions store/state/enum.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package state

type Enum struct {
alexanderbez marked this conversation as resolved.
Show resolved Hide resolved
Value
}

func NewEnum(v Value) Enum {
return Enum{v}
}

func (v Enum) Get(ctx Context) (res byte) {
v.Value.Get(ctx, &res)
return
}

func (v Enum) GetSafe(ctx Context) (res byte, err error) {
v.Value.GetSafe(ctx, &res)
fedekunze marked this conversation as resolved.
Show resolved Hide resolved
return
}

func (v Enum) Set(ctx Context, value byte) {
v.Value.Set(ctx, value)
}

func (v Enum) Incr(ctx Context) (res byte) {
res = v.Get(ctx) + 1
v.Set(ctx, res)
return
}

func (v Enum) Transit(ctx Context, from, to byte) bool {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is this used for?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand the name either

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Transit is used for moving the stored state from from to to. Mostly used for the handshaking process in connection and channel. Named Enum because it is essentially a byte and considered as an enum type. Can be changed.

if v.Get(ctx) != from {
return false
}
v.Set(ctx, to)
return true
}
93 changes: 93 additions & 0 deletions store/state/indexer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package state

import (
"encoding/binary"
"fmt"
"strconv"
)

type IntEncoding byte
alexanderbez marked this conversation as resolved.
Show resolved Hide resolved

const (
Dec IntEncoding = iota
Hex
Bin
)

type Indexer struct {
m Mapping
mossid marked this conversation as resolved.
Show resolved Hide resolved

enc IntEncoding
mossid marked this conversation as resolved.
Show resolved Hide resolved
}

func NewIndexer(base Base, prefix []byte, enc IntEncoding) Indexer {
return Indexer{
m: NewMapping(base, prefix),
enc: enc,
}
}

// Identical length independent from the index, ensure ordering
func EncodeInt(index uint64, enc IntEncoding) (res []byte) {
switch enc {
case Dec:
return []byte(fmt.Sprintf("%020d", index))
case Hex:
return []byte(fmt.Sprintf("%020x", index))
case Bin:
res = make([]byte, 8)
binary.BigEndian.PutUint64(res, index)
return
default:
panic("invalid IntEncoding")
}
}

func DecodeInt(bz []byte, enc IntEncoding) (res uint64, err error) {
switch enc {
case Dec:
return strconv.ParseUint(string(bz), 10, 64)
case Hex:
return strconv.ParseUint(string(bz), 16, 64)
case Bin:
return binary.BigEndian.Uint64(bz), nil
default:
panic("invalid IntEncoding")
}
}

func (ix Indexer) Value(index uint64) Value {
return ix.m.Value(EncodeInt(index, ix.enc))
}

func (ix Indexer) Get(ctx Context, index uint64, ptr interface{}) {
ix.Value(index).Get(ctx, ptr)
}

func (ix Indexer) GetSafe(ctx Context, index uint64, ptr interface{}) error {
return ix.Value(index).GetSafe(ctx, ptr)
}

func (ix Indexer) Set(ctx Context, index uint64, o interface{}) {
ix.Value(index).Set(ctx, o)
}

func (ix Indexer) Has(ctx Context, index uint64) bool {
return ix.Value(index).Exists(ctx)
}

func (ix Indexer) Delete(ctx Context, index uint64) {
ix.Value(index).Delete(ctx)
}

func (ix Indexer) IsEmpty(ctx Context) bool {
return ix.m.IsEmpty(ctx)
}

func (ix Indexer) Prefix(prefix []byte) Indexer {
return Indexer{
m: ix.m.Prefix(prefix),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ix.m undefined (type Indexer has no field or method m) (from typecheck)


enc: ix.enc,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ix.enc undefined (type Indexer has no field or method enc) (from typecheck)

}
}
48 changes: 48 additions & 0 deletions store/state/integer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package state

type Integer struct {
fedekunze marked this conversation as resolved.
Show resolved Hide resolved
Value

enc IntEncoding
mossid marked this conversation as resolved.
Show resolved Hide resolved
}

func NewInteger(v Value, enc IntEncoding) Integer {
return Integer{
Value: v,
enc: enc,
}
}

func (v Integer) Get(ctx Context) (res uint64) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems cleaner if we instead internally call GetSafe but panic on error.

Copy link
Contributor Author

@mossid mossid Jul 25, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Get should panic on unmarshal error, but not on nil value error, so using GetSafe internally will cause type switching on errors

bz := v.GetRaw(ctx)
if bz == nil {
return 0
}
res, err := DecodeInt(bz, v.enc)
if err != nil {
panic(err)
}
return res
}

func (v Integer) GetSafe(ctx Context) (uint64, error) {
bz := v.GetRaw(ctx)
if bz == nil {
return 0, &GetSafeError{}
}
res, err := DecodeInt(bz, v.enc)
if err != nil {
panic(err)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are we panic'ing here? We should rather return an error, no?

}
return res, nil
}

func (v Integer) Set(ctx Context, value uint64) {
v.SetRaw(ctx, EncodeInt(value, v.enc))
}

func (v Integer) Incr(ctx Context) (res uint64) {
mossid marked this conversation as resolved.
Show resolved Hide resolved
res = v.Get(ctx) + 1
v.Set(ctx, res)
return
}
55 changes: 55 additions & 0 deletions store/state/mapping.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package state

type Mapping struct {
alexanderbez marked this conversation as resolved.
Show resolved Hide resolved
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: these are the basic fields used on a Keeper

base Base
start, end []byte
fedekunze marked this conversation as resolved.
Show resolved Hide resolved
}

func NewMapping(base Base, prefix []byte) Mapping {
return Mapping{
base: base.Prefix(prefix),
start: []byte{}, // preventing nil key access in store.Last
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment really has no context.

}
}

func (m Mapping) store(ctx Context) KVStore {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

U1000: func Mapping.store is unused (from unused)

return m.base.store(ctx)
}

func (m Mapping) Value(key []byte) Value {
return NewValue(m.base, key)
}

func (m Mapping) Get(ctx Context, key []byte, ptr interface{}) {
m.Value(key).Get(ctx, ptr)
}

func (m Mapping) GetSafe(ctx Context, key []byte, ptr interface{}) error {
return m.Value(key).GetSafe(ctx, ptr)
}

func (m Mapping) Set(ctx Context, key []byte, o interface{}) {
if o == nil {
m.Delete(ctx, key)
return
}
m.Value(key).Set(ctx, o)
}

func (m Mapping) Has(ctx Context, key []byte) bool {
return m.Value(key).Exists(ctx)
}

func (m Mapping) Delete(ctx Context, key []byte) {
m.Value(key).Delete(ctx)
}

func (m Mapping) IsEmpty(ctx Context) bool {
iter := m.store(ctx).Iterator(nil, nil)
defer iter.Close()
return iter.Valid()
}

func (m Mapping) Prefix(prefix []byte) Mapping {
mossid marked this conversation as resolved.
Show resolved Hide resolved
return NewMapping(m.base, prefix)
}
58 changes: 58 additions & 0 deletions store/state/test_common.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package state

import (
// "testing"
"math/rand"

// "github.com/stretchr/testify/require"

abci "github.com/tendermint/tendermint/abci/types"
dbm "github.com/tendermint/tendermint/libs/db"
"github.com/tendermint/tendermint/libs/log"

"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/store"
sdk "github.com/cosmos/cosmos-sdk/types"
)

const testsize = 10
fedekunze marked this conversation as resolved.
Show resolved Hide resolved

type test interface {
test()
}

type teststruct struct {
I uint64
B bool
SL []byte
}

var _ test = teststruct{}

func (teststruct) test() {}

func newtest() test {
fedekunze marked this conversation as resolved.
Show resolved Hide resolved
var res teststruct
res.I = rand.Uint64()
res.B = rand.Int()%2 == 0
fedekunze marked this conversation as resolved.
Show resolved Hide resolved
res.SL = make([]byte, 20)
rand.Read(res.SL)
fedekunze marked this conversation as resolved.
Show resolved Hide resolved
return res
}

func defaultComponents() (sdk.StoreKey, Context, *codec.Codec) {
fedekunze marked this conversation as resolved.
Show resolved Hide resolved
key := sdk.NewKVStoreKey("test")
db := dbm.NewMemDB()
cms := store.NewCommitMultiStore(db)
cms.MountStoreWithDB(key, sdk.StoreTypeIAVL, db)
err := cms.LoadLatestVersion()
if err != nil {
panic(err)
}
ctx := sdk.NewContext(cms, abci.Header{}, false, log.NewNopLogger())
cdc := codec.New()
cdc.RegisterInterface((*test)(nil), nil)
cdc.RegisterConcrete(teststruct{}, "test/struct", nil)
cdc.Seal()
return key, ctx, cdc
}
8 changes: 8 additions & 0 deletions store/state/types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package state

import (
sdk "github.com/cosmos/cosmos-sdk/types"
)

type KVStore = sdk.KVStore
type Context = sdk.Context
Loading