Skip to content

Commit

Permalink
Merge branch 'master' into ryan/ecocredit-audit
Browse files Browse the repository at this point in the history
  • Loading branch information
ryanchristo authored Sep 8, 2021
2 parents 69a8fbc + 8cae9dd commit b4d677c
Show file tree
Hide file tree
Showing 37 changed files with 736 additions and 548 deletions.
9 changes: 8 additions & 1 deletion app/stable_appconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@
package app

import (
"encoding/json"

abci "github.com/tendermint/tendermint/abci/types"

"github.com/cosmos/cosmos-sdk/baseapp"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/codec/types"
Expand Down Expand Up @@ -72,7 +76,10 @@ func (app *RegenApp) registerUpgradeHandlers() {

gen := ecocredittypes.DefaultGenesisState()
gen.Params.AllowlistEnabled = true
app.mm.Modules[ecocredittypes.ModuleName].InitGenesis(ctx, app.appCodec, app.cdc.MustMarshalJSON(gen))

modules := make(map[string]json.RawMessage)
modules[ecocredittypes.ModuleName] = app.cdc.MustMarshalJSON(gen)
app.smm.InitGenesis(ctx, modules, []abci.ValidatorUpdate{})

return app.mm.RunMigrations(ctx, app.configurator, fromVM)
})
Expand Down
2 changes: 1 addition & 1 deletion app/testsuite/network_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ func DefaultConfig() network.Config {
BondDenom: sdk.DefaultBondDenom,
MinGasPrices: fmt.Sprintf("0.000006%s", sdk.DefaultBondDenom),
AccountTokens: sdk.TokensFromConsensusPower(1000, sdk.DefaultPowerReduction),
StakingTokens: sdk.TokensFromConsensusPower(1000, sdk.DefaultPowerReduction),
StakingTokens: sdk.TokensFromConsensusPower(1e7, sdk.DefaultPowerReduction),
BondedTokens: sdk.TokensFromConsensusPower(100, sdk.DefaultPowerReduction),
PruningStrategy: storetypes.PruningOptionNothing,
CleanupDir: true,
Expand Down
1 change: 1 addition & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -1275,5 +1275,6 @@ pgregory.net/rapid v0.4.7/go.mod h1:UYpPVyjFHzYBGHIxLFoupi8vwk6rXNzRY9OMvVxFIOU=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs=
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU=
61 changes: 45 additions & 16 deletions orm/auto_uint64.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package orm
import (
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/errors"
)

var _ Indexable = &AutoUInt64TableBuilder{}
Expand Down Expand Up @@ -37,7 +38,6 @@ func (a AutoUInt64TableBuilder) Build() AutoUInt64Table {
}
}

var _ SequenceExportable = &AutoUInt64Table{}
var _ TableExportable = &AutoUInt64Table{}

// AutoUInt64Table is the table type which an auto incrementing ID.
Expand All @@ -46,8 +46,11 @@ type AutoUInt64Table struct {
seq Sequence
}

// Create a new persistent object with an auto generated uint64 primary key. They key is returned.
// Create iterates though the registered callbacks and may add secondary index keys by them.
// Create a new persistent object with an auto generated uint64 primary key. The
// key is returned.
//
// Create iterates through the registered callbacks that may add secondary index
// keys.
func (a AutoUInt64Table) Create(ctx HasKVStore, obj codec.ProtoMarshaler) (uint64, error) {
autoIncID := a.seq.NextVal(ctx)
err := a.table.Create(ctx, EncodeSequence(autoIncID), obj)
Expand All @@ -57,20 +60,32 @@ func (a AutoUInt64Table) Create(ctx HasKVStore, obj codec.ProtoMarshaler) (uint6
return autoIncID, nil
}

// Save updates the given object under the rowID key. It expects the key to exists already
// and fails with an `ErrNotFound` otherwise. Any caller must therefore make sure that this contract
// is fulfilled. Parameters must not be nil.
// Update updates the given object under the rowID key. It expects the key to
// exists already and fails with an `ErrNotFound` otherwise. Any caller must
// therefore make sure that this contract is fulfilled. Parameters must not be
// nil.
//
// Save iterates though the registered callbacks and may add or remove secondary index keys by them.
func (a AutoUInt64Table) Save(ctx HasKVStore, rowID uint64, newValue codec.ProtoMarshaler) error {
return a.table.Save(ctx, EncodeSequence(rowID), newValue)
// Update iterates through the registered callbacks that may add or remove
// secondary index keys.
func (a AutoUInt64Table) Update(ctx HasKVStore, rowID uint64, newValue codec.ProtoMarshaler) error {
return a.table.Update(ctx, EncodeSequence(rowID), newValue)
}

// Delete removes the object under the rowID key. It expects the key to exists already
// and fails with a `ErrNotFound` otherwise. Any caller must therefore make sure that this contract
// is fulfilled.
// Set persists the given object under the rowID key. It does not check if the
// key already exists and overwrites the value if it does.
//
// Delete iterates though the registered callbacks and removes secondary index keys by them.
// Set iterates through the registered callbacks that may add secondary index
// keys.
func (a AutoUInt64Table) Set(ctx HasKVStore, rowID uint64, newValue codec.ProtoMarshaler) error {
return a.table.Set(ctx, EncodeSequence(rowID), newValue)
}

// Delete removes the object under the rowID key. It expects the key to exists
// already and fails with a `ErrNotFound` otherwise. Any caller must therefore
// make sure that this contract is fulfilled.
//
// Delete iterates through the registered callbacks that remove secondary index
// keys.
func (a AutoUInt64Table) Delete(ctx HasKVStore, rowID uint64) error {
return a.table.Delete(ctx, EncodeSequence(rowID))
}
Expand Down Expand Up @@ -128,7 +143,21 @@ func (a AutoUInt64Table) Sequence() Sequence {
return a.seq
}

// Table satisfies the TableExportable interface and must not be used otherwise.
func (a AutoUInt64Table) Table() table {
return a.table
// Export stores all the values in the table in the passed ModelSlicePtr and
// returns the current value of the associated sequence.
func (a AutoUInt64Table) Export(ctx HasKVStore, dest ModelSlicePtr) (uint64, error) {
_, err := a.table.Export(ctx, dest)
if err != nil {
return 0, err
}
return a.seq.CurVal(ctx), nil
}

// Import clears the table and initializes it from the given data interface{}.
// data should be a slice of structs that implement PrimaryKeyed.
func (a AutoUInt64Table) Import(ctx HasKVStore, data interface{}, seqValue uint64) error {
if err := a.seq.InitVal(ctx, seqValue); err != nil {
return errors.Wrap(err, "sequence")
}
return a.table.Import(ctx, data, seqValue)
}
17 changes: 17 additions & 0 deletions orm/generators_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package orm_test

import (
"pgregory.net/rapid"

"github.com/regen-network/regen-ledger/orm/testdata"
)

// genGroupMember generates a new group member. At the moment it doesn't
// generate empty strings for Group or Member.
var genGroupMember = rapid.Custom(func(t *rapid.T) *testdata.GroupMember {
return &testdata.GroupMember{
Group: []byte(rapid.StringN(1, 100, 150).Draw(t, "group").(string)),
Member: []byte(rapid.StringN(1, 100, 150).Draw(t, "member").(string)),
Weight: rapid.Uint64().Draw(t, "weight").(uint64),
}
})
93 changes: 10 additions & 83 deletions orm/genesis.go
Original file line number Diff line number Diff line change
@@ -1,88 +1,15 @@
package orm

import (
"reflect"

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

// TableExportable
type TableExportable interface {
// Table returns the table to export
Table() table
}

// SequenceExportable
type SequenceExportable interface {
// Sequence returns the sequence to export
Sequence() Sequence
}

// ExportTableData iterates over the given table entries and stores them at the passed ModelSlicePtr.
// When the given table implements the `SequenceExportable` interface then it's current value
// is returned as well or otherwise defaults to 0.
func ExportTableData(ctx HasKVStore, t TableExportable, dest ModelSlicePtr) (uint64, error) {
it, err := t.Table().PrefixScan(ctx, nil, nil)
if err != nil {
return 0, errors.Wrap(err, "table PrefixScan failure when exporting table data")
}
_, err = ReadAll(it, dest)
if err != nil {
return 0, err
}
var seqValue uint64
if st, ok := t.(SequenceExportable); ok {
seqValue = st.Sequence().CurVal(ctx)
}
return seqValue, err
}

// ImportTableData initializes a table and attaches indexers from the given data interface{}.
// data should be a slice of structs that implement PrimaryKeyed (eg []*GroupInfo).
// The seqValue is optional and only used with tables that implement the `SequenceExportable` interface.
func ImportTableData(ctx HasKVStore, t TableExportable, data interface{}, seqValue uint64) error {
table := t.Table()
if err := clearAllInTable(ctx, table); err != nil {
return errors.Wrap(err, "clear old entries")
}

if st, ok := t.(SequenceExportable); ok {
if err := st.Sequence().InitVal(ctx, seqValue); err != nil {
return errors.Wrap(err, "sequence")
}
}

// Provided data must be a slice
modelSlice := reflect.ValueOf(data)
if modelSlice.Kind() != reflect.Slice {
return errors.Wrap(ErrArgument, "data must be a slice")
}

// Create table entries
for i := 0; i < modelSlice.Len(); i++ {
obj, ok := modelSlice.Index(i).Interface().(PrimaryKeyed)
if !ok {
return errors.Wrapf(ErrArgument, "unsupported type :%s", reflect.TypeOf(data).Elem().Elem())
}
err := table.Create(ctx, PrimaryKey(obj), obj)
if err != nil {
return err
}
}

return nil
}

// clearAllInTable deletes all entries in a table with delete interceptors called
func clearAllInTable(ctx HasKVStore, table table) error {
store := prefix.NewStore(ctx.KVStore(table.storeKey), []byte{table.prefix})
it := store.Iterator(nil, nil)
defer it.Close()
for ; it.Valid(); it.Next() {
if err := table.Delete(ctx, it.Key()); err != nil {
return err
}
}
return nil
// Export stores all the values in the table in the passed
// ModelSlicePtr. If the table has an associated sequence, then its
// current value is returned, otherwise 0 is returned by default.
Export(HasKVStore, ModelSlicePtr) (uint64, error)

// Import clears the table and initializes it from the given data
// interface{}. data should be a slice of structs that implement
// PrimaryKeyed (eg []*GroupInfo). The seqValue is optional and only
// used with tables that have an associated sequence.
Import(HasKVStore, interface{}, uint64) error
}
4 changes: 2 additions & 2 deletions orm/genesis_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ func TestImportExportTableData(t *testing.T) {
},
}

err = orm.ImportTableData(ctx, table, groups, 2)
err = table.Import(ctx, groups, 2)
require.NoError(t, err)

for _, g := range groups {
Expand All @@ -46,7 +46,7 @@ func TestImportExportTableData(t *testing.T) {
}

var exported []*testdata.GroupInfo
seq, err := orm.ExportTableData(ctx, table, &exported)
seq, err := table.Export(ctx, &exported)
require.NoError(t, err)
require.Equal(t, seq, uint64(2))

Expand Down
2 changes: 1 addition & 1 deletion orm/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ require (
github.com/gogo/protobuf v1.3.3
github.com/stretchr/testify v1.7.0
github.com/tendermint/tm-db v0.6.4
pgregory.net/rapid v0.4.7 // indirect
pgregory.net/rapid v0.4.7
)

replace github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1
4 changes: 2 additions & 2 deletions orm/index.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ func newIndex(builder Indexable, prefix byte, indexer *Indexer) (MultiKeyIndex,
indexer: indexer,
indexKeyCodec: codec,
}
builder.AddAfterSaveInterceptor(idx.onSave)
builder.AddAfterSetInterceptor(idx.onSet)
builder.AddAfterDeleteInterceptor(idx.onDelete)
return idx, nil
}
Expand Down Expand Up @@ -135,7 +135,7 @@ func (i MultiKeyIndex) ReversePrefixScan(ctx HasKVStore, start []byte, end []byt
return indexIterator{ctx: ctx, it: it, rowGetter: i.rowGetter, keyCodec: i.indexKeyCodec}, nil
}

func (i MultiKeyIndex) onSave(ctx HasKVStore, rowID RowID, newValue, oldValue codec.ProtoMarshaler) error {
func (i MultiKeyIndex) onSet(ctx HasKVStore, rowID RowID, newValue, oldValue codec.ProtoMarshaler) error {
store := prefix.NewStore(ctx.KVStore(i.storeKey), []byte{i.prefix})
if oldValue == nil {
return i.indexer.OnCreate(store, rowID, newValue)
Expand Down
61 changes: 61 additions & 0 deletions orm/index_property_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package orm_test

import (
"testing"

"pgregory.net/rapid"

"github.com/regen-network/regen-ledger/orm"
"github.com/stretchr/testify/require"
)

func TestPrefixRangeProperty(t *testing.T) {
t.Run("TestPrefixRange", rapid.MakeCheck(func(t *rapid.T) {
prefix := rapid.SliceOf(rapid.Byte()).Draw(t, "prefix").([]byte)

start, end := orm.PrefixRange(prefix)

// len(prefix) == 0 => start == nil && end == nil
if len(prefix) == 0 {
require.Nil(t, start)
require.Nil(t, end)
} else {
// start == prefix
require.Equal(t, prefix, start)

// Would overflow if all bytes are 255
wouldOverflow := true
for _, b := range prefix {
if b != 255 {
wouldOverflow = false
}
}

// Overflow => end == nil
if wouldOverflow {
require.Nil(t, end)
} else {
require.Equal(t, len(start), len(end))

// Scan back and find last value that isn't 255
overflowIndex := len(start) - 1
for overflowIndex > 0 && prefix[overflowIndex] == 255 {
overflowIndex--
}

// bytes should be the same up to overflow
// index, one greater at overflow and 0 from
// then on
for i, b := range start {
if i < overflowIndex {
require.Equal(t, b, end[i])
} else if i == overflowIndex {
require.Equal(t, b+1, end[i])
} else {
require.Equal(t, uint8(0), end[i])
}
}
}
}
}))
}
6 changes: 3 additions & 3 deletions orm/index_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ func (b *nilCodecBuilder) RowGetter() orm.RowGetter {
return func(a orm.HasKVStore, b orm.RowID, c codec.ProtoMarshaler) error { return nil }
}
func (b *nilCodecBuilder) IndexKeyCodec() orm.IndexKeyCodec { return nil }
func (b *nilCodecBuilder) AddAfterSaveInterceptor(orm.AfterSaveInterceptor) {}
func (b *nilCodecBuilder) AddAfterSetInterceptor(orm.AfterSetInterceptor) {}
func (b *nilCodecBuilder) AddAfterDeleteInterceptor(orm.AfterDeleteInterceptor) {}

type nilStoreKeyBuilder struct{}
Expand All @@ -39,7 +39,7 @@ func (b *nilStoreKeyBuilder) RowGetter() orm.RowGetter {
func (b *nilStoreKeyBuilder) IndexKeyCodec() orm.IndexKeyCodec {
return orm.Max255DynamicLengthIndexKeyCodec{}
}
func (b *nilStoreKeyBuilder) AddAfterSaveInterceptor(orm.AfterSaveInterceptor) {}
func (b *nilStoreKeyBuilder) AddAfterSetInterceptor(orm.AfterSetInterceptor) {}
func (b *nilStoreKeyBuilder) AddAfterDeleteInterceptor(orm.AfterDeleteInterceptor) {}

type nilRowGetterBuilder struct{}
Expand All @@ -53,7 +53,7 @@ func (b *nilRowGetterBuilder) RowGetter() orm.RowGetter {
func (b *nilRowGetterBuilder) IndexKeyCodec() orm.IndexKeyCodec {
return orm.Max255DynamicLengthIndexKeyCodec{}
}
func (b *nilRowGetterBuilder) AddAfterSaveInterceptor(orm.AfterSaveInterceptor) {}
func (b *nilRowGetterBuilder) AddAfterSetInterceptor(orm.AfterSetInterceptor) {}
func (b *nilRowGetterBuilder) AddAfterDeleteInterceptor(orm.AfterDeleteInterceptor) {}

func TestNewIndex(t *testing.T) {
Expand Down
Loading

0 comments on commit b4d677c

Please sign in to comment.