Skip to content

Commit

Permalink
Merge branch 'main' into julien/migrations
Browse files Browse the repository at this point in the history
  • Loading branch information
julienrbrt authored Feb 7, 2024
2 parents 6153444 + cd1da8d commit d973b87
Show file tree
Hide file tree
Showing 81 changed files with 333 additions and 177 deletions.
5 changes: 3 additions & 2 deletions .github/workflows/starship-tests.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
name: Starship E2E Tests
# E2E tests using Starship, run on a schedule
on:
schedule:
- cron: "0 */6 * * *" # every 6 hours
# schedule:
# - cron: "0 */6 * * *" # every 6 hours
workflow_dispatch:

permissions:
contents: read
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ Every module contains its own CHANGELOG.md. Please refer to the module you are i
* (baseapp) [#18551](https://github.com/cosmos/cosmos-sdk/pull/18551) Fix SelectTxForProposal the calculation method of tx bytes size is inconsistent with CometBFT
* (abci): [#19200](https://github.com/cosmos/cosmos-sdk/pull/19200) Ensure that sdk side ve math matches cometbft
* (server) [#18994](https://github.com/cosmos/cosmos-sdk/pull/18994) Update server context directly rather than a reference to a sub-object
* (crypto) [#19371](https://github.com/cosmos/cosmos-sdk/pull/19371) Avoid cli redundant log in stdout, log to stderr instead.

### API Breaking Changes

Expand Down
2 changes: 1 addition & 1 deletion client/v2/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ require (
require (
cosmossdk.io/collections v0.4.0 // indirect
cosmossdk.io/errors v1.0.1 // indirect
cosmossdk.io/log v1.3.0 // indirect
cosmossdk.io/log v1.3.1 // indirect
cosmossdk.io/math v1.2.0 // indirect
cosmossdk.io/store v1.0.2 // indirect
cosmossdk.io/x/auth v0.0.0-00010101000000-000000000000
Expand Down
4 changes: 2 additions & 2 deletions client/v2/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ cosmossdk.io/collections v0.4.0 h1:PFmwj2W8szgpD5nOd8GWH6AbYNi1f2J6akWXJ7P5t9s=
cosmossdk.io/collections v0.4.0/go.mod h1:oa5lUING2dP+gdDquow+QjlF45eL1t4TJDypgGd+tv0=
cosmossdk.io/errors v1.0.1 h1:bzu+Kcr0kS/1DuPBtUFdWjzLqyUuCiyHjyJB6srBV/0=
cosmossdk.io/errors v1.0.1/go.mod h1:MeelVSZThMi4bEakzhhhE/CKqVv3nOJDA25bIqRDu/U=
cosmossdk.io/log v1.3.0 h1:L0Z0XstClo2kOU4h3V1iDoE5Ji64sg5HLOogzGg67Oo=
cosmossdk.io/log v1.3.0/go.mod h1:HIDyvWLqZe2ovlWabsDN4aPMpY/nUEquAhgfTf2ZzB8=
cosmossdk.io/log v1.3.1 h1:UZx8nWIkfbbNEWusZqzAx3ZGvu54TZacWib3EzUYmGI=
cosmossdk.io/log v1.3.1/go.mod h1:2/dIomt8mKdk6vl3OWJcPk2be3pGOS8OQaLUM/3/tCM=
cosmossdk.io/math v1.2.0 h1:8gudhTkkD3NxOP2YyyJIYYmt6dQ55ZfJkDOaxXpy7Ig=
cosmossdk.io/math v1.2.0/go.mod h1:l2Gnda87F0su8a/7FEKJfFdJrM0JZRXQaohlgJeyQh0=
cosmossdk.io/store v1.0.2 h1:lSg5BTvJBHUDwswNNyeh4K/CbqiHER73VU4nDNb8uk0=
Expand Down
3 changes: 2 additions & 1 deletion collections/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ Ref: https://keepachangelog.com/en/1.0.0/

### Features

* [#18933](https://github.com/cosmos/cosmos-sdk/pull/18933) Add LookupMap implementation. It is basic wrapping of the standard Map methods but is not iterable.
* [#19343](https://github.com/cosmos/cosmos-sdk/pull/19343) – Simplify IndexedMap creation by allowing to infer indexes through reflection.
* [#18933](https://github.com/cosmos/cosmos-sdk/pull/18933) – Add LookupMap implementation. It is basic wrapping of the standard Map methods but is not iterable.
* [#17656](https://github.com/cosmos/cosmos-sdk/pull/17656) – Introduces `Vec`, a collection type that allows to represent a growable array on top of a KVStore.

## [v0.4.0](https://github.com/cosmos/cosmos-sdk/releases/tag/collections%2Fv0.4.0)
Expand Down
20 changes: 12 additions & 8 deletions collections/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -837,10 +837,6 @@ type AccountsIndexes struct {
Number *indexes.Unique[uint64, sdk.AccAddress, authtypes.BaseAccount]
}

func (a AccountsIndexes) IndexesList() []collections.Index[sdk.AccAddress, authtypes.BaseAccount] {
return []collections.Index[sdk.AccAddress, authtypes.BaseAccount]{a.Number}
}

func NewAccountIndexes(sb *collections.SchemaBuilder) AccountsIndexes {
return AccountsIndexes{
Number: indexes.NewUnique(
Expand All @@ -867,15 +863,23 @@ Where the first type parameter is `uint64`, which is the field type of our index
The second type parameter is the primary key `sdk.AccAddress`
And the third type parameter is the actual object we're storing `authtypes.BaseAccount`.

Then we implement a function called `IndexesList` on our `AccountIndexes` struct, this will be used
by the `IndexedMap` to keep the underlying map in sync with the indexes, in our case `Number`.
This function just needs to return the slice of indexes contained in the struct.

Then we create a `NewAccountIndexes` function that instantiates and returns the `AccountsIndexes` struct.

The function takes a `SchemaBuilder`. Then we instantiate our `indexes.Unique`, let's analyse the arguments we pass to
`indexes.NewUnique`.

#### NOTE: indexes list

The `AccountsIndexes` struct contains the indexes, the `NewIndexedMap` function will infer the indexes form that struct
using reflection, this happens only at init and is not computationally expensive. In case you want to explicitly declare
indexes: implement the `Indexes` interface in the `AccountsIndexes` struct:

```go
func (a AccountsIndexes) IndexesList() []collections.Index[sdk.AccAddress, authtypes.BaseAccount] {
return []collections.Index[sdk.AccAddress, authtypes.BaseAccount]{a.Number}
}
```

#### Instantiating a `indexes.Unique`

The first three arguments, we already know them, they are: `SchemaBuilder`, `Prefix` which is our index prefix (the partition
Expand Down
84 changes: 74 additions & 10 deletions collections/indexed_map.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ package collections

import (
"context"
"errors"
"fmt"
"reflect"

"cosmossdk.io/collections/codec"
)
Expand Down Expand Up @@ -32,28 +35,89 @@ type Index[PrimaryKey, Value any] interface {
// Internally IndexedMap can be seen as a partitioned collection, one partition
// is a Map[PrimaryKey, Value], that maintains the object, the second
// are the Indexes.
type IndexedMap[PrimaryKey, Value any, Idx Indexes[PrimaryKey, Value]] struct {
Indexes Idx
m Map[PrimaryKey, Value]
type IndexedMap[PrimaryKey, Value, Idx any] struct {
Indexes Idx
computedIndexes []Index[PrimaryKey, Value]
m Map[PrimaryKey, Value]
}

// NewIndexedMapSafe behaves like NewIndexedMap but returns errors.
func NewIndexedMapSafe[K, V, I any](
schema *SchemaBuilder,
prefix Prefix,
name string,
pkCodec codec.KeyCodec[K],
valueCodec codec.ValueCodec[V],
indexes I,
) (im *IndexedMap[K, V, I], err error) {
var indexesList []Index[K, V]
indexesImpl, ok := any(indexes).(Indexes[K, V])
if ok {
indexesList = indexesImpl.IndexesList()
} else {
// if does not implement Indexes, then we try to infer using reflection
indexesList, err = tryInferIndexes[I, K, V](indexes)
if err != nil {
return nil, fmt.Errorf("unable to infer indexes using reflection, consider implementing Indexes interface: %w", err)
}
}

return &IndexedMap[K, V, I]{
computedIndexes: indexesList,
Indexes: indexes,
m: NewMap(schema, prefix, name, pkCodec, valueCodec),
}, nil
}

var (
// testing sentinel errors
errNotStruct = errors.New("wanted struct or pointer to a struct")
errNotIndex = errors.New("field is not an index implementation")
)

func tryInferIndexes[I, K, V any](indexes I) ([]Index[K, V], error) {
typ := reflect.TypeOf(indexes)
v := reflect.ValueOf(indexes)
// check if struct or pointer to a struct
if typ.Kind() != reflect.Struct && (typ.Kind() != reflect.Pointer || typ.Elem().Kind() != reflect.Struct) {
return nil, fmt.Errorf("%w: type %v", errNotStruct, typ)
}
// dereference
if typ.Kind() == reflect.Pointer {
v = v.Elem()
}
indexesImpl := make([]Index[K, V], v.NumField())
for i := 0; i < v.NumField(); i++ {
field := v.Field(i)
index, ok := field.Interface().(Index[K, V])
if !ok {
return nil, fmt.Errorf("%w: field number %d", errNotIndex, i)
}
indexesImpl[i] = index
}
return indexesImpl, nil
}

// NewIndexedMap instantiates a new IndexedMap. Accepts a SchemaBuilder, a Prefix,
// a humanized name that defines the name of the collection, the primary key codec
// which is basically what IndexedMap uses to encode the primary key to bytes,
// the value codec which is what the IndexedMap uses to encode the value.
// Then it expects the initialized indexes.
func NewIndexedMap[PrimaryKey, Value any, Idx Indexes[PrimaryKey, Value]](
// Then it expects the initialized indexes. Reflection is used to infer the
// indexes, Indexes can optionally be implemented to be explicit. Panics
// on failure to create indexes. If you want an erroring API use NewIndexedMapSafe.
func NewIndexedMap[PrimaryKey, Value, Idx any](
schema *SchemaBuilder,
prefix Prefix,
name string,
pkCodec codec.KeyCodec[PrimaryKey],
valueCodec codec.ValueCodec[Value],
indexes Idx,
) *IndexedMap[PrimaryKey, Value, Idx] {
return &IndexedMap[PrimaryKey, Value, Idx]{
Indexes: indexes,
m: NewMap(schema, prefix, name, pkCodec, valueCodec),
im, err := NewIndexedMapSafe(schema, prefix, name, pkCodec, valueCodec, indexes)
if err != nil {
panic(err)
}
return im
}

// Get gets the object given its primary key.
Expand Down Expand Up @@ -111,7 +175,7 @@ func (m *IndexedMap[PrimaryKey, Value, Idx]) ValueCodec() codec.ValueCodec[Value
}

func (m *IndexedMap[PrimaryKey, Value, Idx]) ref(ctx context.Context, pk PrimaryKey, value Value) error {
for _, index := range m.Indexes.IndexesList() {
for _, index := range m.computedIndexes {
err := index.Reference(ctx, pk, value, cachedGet[PrimaryKey, Value](ctx, m, pk))
if err != nil {
return err
Expand All @@ -121,7 +185,7 @@ func (m *IndexedMap[PrimaryKey, Value, Idx]) ref(ctx context.Context, pk Primary
}

func (m *IndexedMap[PrimaryKey, Value, Idx]) unref(ctx context.Context, pk PrimaryKey) error {
for _, index := range m.Indexes.IndexesList() {
for _, index := range m.computedIndexes {
err := index.Unreference(ctx, pk, cachedGet[PrimaryKey, Value](ctx, m, pk))
if err != nil {
return err
Expand Down
30 changes: 30 additions & 0 deletions collections/indexed_map_internal_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package collections

import (
"testing"

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

func TestTryInferIndex(t *testing.T) {
invalidIdx := 5

t.Run("not a pointer to struct", func(t *testing.T) {
_, err := tryInferIndexes[*int, string, string](&invalidIdx)
require.ErrorIs(t, err, errNotStruct)
})

t.Run("not a struct", func(t *testing.T) {
_, err := tryInferIndexes[int, string, string](invalidIdx)
require.ErrorIs(t, err, errNotStruct)
})

t.Run("not an index field", func(t *testing.T) {
type invalidIndex struct {
A int
}

_, err := tryInferIndexes[invalidIndex, string, string](invalidIndex{})
require.ErrorIs(t, err, errNotIndex)
})
}
24 changes: 24 additions & 0 deletions collections/indexed_map_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,3 +104,27 @@ func TestIndexedMap(t *testing.T) {
require.NoError(t, err)
require.Equal(t, company{"milan", 4}, v)
}

type inferIndex struct {
City *indexes.Multi[string, string, company]
Vat *indexes.Unique[uint64, string, company]
}

func newInferIndex(schema *collections.SchemaBuilder) *inferIndex {
return &inferIndex{
City: indexes.NewMulti(schema, collections.NewPrefix(1), "companies_by_city", collections.StringKey, collections.StringKey, func(pk string, value company) (string, error) {
return value.City, nil
}),
Vat: indexes.NewUnique(schema, collections.NewPrefix(2), "companies_by_vat", collections.Uint64Key, collections.StringKey, func(pk string, value company) (uint64, error) {
return value.Vat, nil
}),
}
}

func TestIndexedMapInfer(t *testing.T) {
sk, _ := colltest.MockStore()
schema := collections.NewSchemaBuilder(sk)

_, err := collections.NewIndexedMapSafe(schema, collections.NewPrefix(0), "im", collections.StringKey, colltest.MockValueCodec[company](), newInferIndex(schema))
require.NoError(t, err)
}
4 changes: 2 additions & 2 deletions crypto/keyring/keyring.go
Original file line number Diff line number Diff line change
Expand Up @@ -916,7 +916,7 @@ func (ks keystore) MigrateAll() ([]*Record, error) {

rec, err := ks.migrate(key)
if err != nil {
fmt.Printf("migrate err for key %s: %q\n", key, err)
fmt.Fprintf(os.Stderr, "migrate err for key %s: %q\n", key, err)
continue
}

Expand Down Expand Up @@ -990,7 +990,7 @@ func (ks keystore) migrate(key string) (*Record, error) {
return nil, errorsmod.Wrap(err, "unable to set keyring.Item")
}

fmt.Printf("Successfully migrated key %s.\n", key)
fmt.Fprintf(os.Stderr, "Successfully migrated key %s.\n", key)

return k, nil
}
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ require (
cosmossdk.io/core v0.12.1-0.20231114100755-569e3ff6a0d7
cosmossdk.io/depinject v1.0.0-alpha.4
cosmossdk.io/errors v1.0.1
cosmossdk.io/log v1.3.0
cosmossdk.io/log v1.3.1
cosmossdk.io/math v1.2.0
cosmossdk.io/store v1.0.2
cosmossdk.io/x/auth v0.0.0-00010101000000-000000000000
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ cosmossdk.io/collections v0.4.0 h1:PFmwj2W8szgpD5nOd8GWH6AbYNi1f2J6akWXJ7P5t9s=
cosmossdk.io/collections v0.4.0/go.mod h1:oa5lUING2dP+gdDquow+QjlF45eL1t4TJDypgGd+tv0=
cosmossdk.io/errors v1.0.1 h1:bzu+Kcr0kS/1DuPBtUFdWjzLqyUuCiyHjyJB6srBV/0=
cosmossdk.io/errors v1.0.1/go.mod h1:MeelVSZThMi4bEakzhhhE/CKqVv3nOJDA25bIqRDu/U=
cosmossdk.io/log v1.3.0 h1:L0Z0XstClo2kOU4h3V1iDoE5Ji64sg5HLOogzGg67Oo=
cosmossdk.io/log v1.3.0/go.mod h1:HIDyvWLqZe2ovlWabsDN4aPMpY/nUEquAhgfTf2ZzB8=
cosmossdk.io/log v1.3.1 h1:UZx8nWIkfbbNEWusZqzAx3ZGvu54TZacWib3EzUYmGI=
cosmossdk.io/log v1.3.1/go.mod h1:2/dIomt8mKdk6vl3OWJcPk2be3pGOS8OQaLUM/3/tCM=
cosmossdk.io/math v1.2.0 h1:8gudhTkkD3NxOP2YyyJIYYmt6dQ55ZfJkDOaxXpy7Ig=
cosmossdk.io/math v1.2.0/go.mod h1:l2Gnda87F0su8a/7FEKJfFdJrM0JZRXQaohlgJeyQh0=
cosmossdk.io/store v1.0.2 h1:lSg5BTvJBHUDwswNNyeh4K/CbqiHER73VU4nDNb8uk0=
Expand Down
2 changes: 1 addition & 1 deletion simapp/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ require (
cosmossdk.io/collections v0.4.0
cosmossdk.io/core v0.12.1-0.20231114100755-569e3ff6a0d7
cosmossdk.io/depinject v1.0.0-alpha.4
cosmossdk.io/log v1.3.0
cosmossdk.io/log v1.3.1
cosmossdk.io/math v1.2.0
cosmossdk.io/store v1.0.2
cosmossdk.io/tools/confix v0.0.0-20230613133644-0a778132a60f
Expand Down
4 changes: 2 additions & 2 deletions simapp/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -188,8 +188,8 @@ cosmossdk.io/collections v0.4.0 h1:PFmwj2W8szgpD5nOd8GWH6AbYNi1f2J6akWXJ7P5t9s=
cosmossdk.io/collections v0.4.0/go.mod h1:oa5lUING2dP+gdDquow+QjlF45eL1t4TJDypgGd+tv0=
cosmossdk.io/errors v1.0.1 h1:bzu+Kcr0kS/1DuPBtUFdWjzLqyUuCiyHjyJB6srBV/0=
cosmossdk.io/errors v1.0.1/go.mod h1:MeelVSZThMi4bEakzhhhE/CKqVv3nOJDA25bIqRDu/U=
cosmossdk.io/log v1.3.0 h1:L0Z0XstClo2kOU4h3V1iDoE5Ji64sg5HLOogzGg67Oo=
cosmossdk.io/log v1.3.0/go.mod h1:HIDyvWLqZe2ovlWabsDN4aPMpY/nUEquAhgfTf2ZzB8=
cosmossdk.io/log v1.3.1 h1:UZx8nWIkfbbNEWusZqzAx3ZGvu54TZacWib3EzUYmGI=
cosmossdk.io/log v1.3.1/go.mod h1:2/dIomt8mKdk6vl3OWJcPk2be3pGOS8OQaLUM/3/tCM=
cosmossdk.io/math v1.2.0 h1:8gudhTkkD3NxOP2YyyJIYYmt6dQ55ZfJkDOaxXpy7Ig=
cosmossdk.io/math v1.2.0/go.mod h1:l2Gnda87F0su8a/7FEKJfFdJrM0JZRXQaohlgJeyQh0=
cosmossdk.io/store v1.0.2 h1:lSg5BTvJBHUDwswNNyeh4K/CbqiHER73VU4nDNb8uk0=
Expand Down
4 changes: 2 additions & 2 deletions simapp/gomod2nix.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ schema = 3
version = "v1.0.1"
hash = "sha256-MgTocXkBzri9FKkNtkARJXPmxRrRO/diQJS5ZzvYrJY="
[mod."cosmossdk.io/log"]
version = "v1.3.0"
hash = "sha256-ti835PlPIWxP8c2Drfo5asi2Kd6kBkmXaadQZ/BiMqw="
version = "v1.3.1"
hash = "sha256-otkUvsz35VuuUWXoTmWBwR61+o6YzvWETGdLfwWDvwY="
[mod."cosmossdk.io/math"]
version = "v1.2.0"
hash = "sha256-yLPUAsJPQxuI0C22cPbP/BzclWb9eBzGFntGDQmdVUc="
Expand Down
2 changes: 1 addition & 1 deletion store/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ go 1.21
require (
cosmossdk.io/core v0.12.0
cosmossdk.io/errors v1.0.1
cosmossdk.io/log v1.3.0
cosmossdk.io/log v1.3.1
github.com/cockroachdb/errors v1.11.1
github.com/cockroachdb/pebble v1.0.0
github.com/cometbft/cometbft v0.38.5
Expand Down
4 changes: 2 additions & 2 deletions store/go.sum
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
cosmossdk.io/errors v1.0.1 h1:bzu+Kcr0kS/1DuPBtUFdWjzLqyUuCiyHjyJB6srBV/0=
cosmossdk.io/errors v1.0.1/go.mod h1:MeelVSZThMi4bEakzhhhE/CKqVv3nOJDA25bIqRDu/U=
cosmossdk.io/log v1.3.0 h1:L0Z0XstClo2kOU4h3V1iDoE5Ji64sg5HLOogzGg67Oo=
cosmossdk.io/log v1.3.0/go.mod h1:HIDyvWLqZe2ovlWabsDN4aPMpY/nUEquAhgfTf2ZzB8=
cosmossdk.io/log v1.3.1 h1:UZx8nWIkfbbNEWusZqzAx3ZGvu54TZacWib3EzUYmGI=
cosmossdk.io/log v1.3.1/go.mod h1:2/dIomt8mKdk6vl3OWJcPk2be3pGOS8OQaLUM/3/tCM=
github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
github.com/DataDog/zstd v1.5.5 h1:oWf5W7GtOLgp6bciQYDmhHHjdhYkALu6S/5Ni9ZgSvQ=
github.com/DataDog/zstd v1.5.5/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw=
Expand Down
4 changes: 2 additions & 2 deletions tests/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ require (
cosmossdk.io/core v0.12.1-0.20231114100755-569e3ff6a0d7
cosmossdk.io/depinject v1.0.0-alpha.4
cosmossdk.io/errors v1.0.1
cosmossdk.io/log v1.3.0
cosmossdk.io/log v1.3.1
cosmossdk.io/math v1.2.0
cosmossdk.io/simapp v0.0.0-20230309163709-87da587416ba
cosmossdk.io/store v1.0.2
Expand Down Expand Up @@ -45,7 +45,7 @@ require (
cosmossdk.io/x/slashing v0.0.0-00010101000000-000000000000
cosmossdk.io/x/staking v0.0.0-00010101000000-000000000000
github.com/google/go-cmp v0.6.0
github.com/jhump/protoreflect v1.15.5
github.com/jhump/protoreflect v1.15.6
)

require (
Expand Down
Loading

0 comments on commit d973b87

Please sign in to comment.