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

WIP: ADR 073: Built-in Indexer Implementation #20547

Closed
wants to merge 208 commits into from
Closed
Show file tree
Hide file tree
Changes from 201 commits
Commits
Show all changes
208 commits
Select commit Hold shift + click to select a range
8cf4e9a
WIP indexer framework
aaronc Jun 4, 2024
fbc0f2a
WIP on v0.50
aaronc Jun 4, 2024
ed07f78
feat(collections): add HasCollections interface
aaronc Jun 4, 2024
1e634b0
update CHANGELOG.md
aaronc Jun 4, 2024
37ccc09
feat(collections): add optional key and naming methods
aaronc Jun 4, 2024
6311f4f
add tests
aaronc Jun 4, 2024
e337c84
update CHANGELOG.md
aaronc Jun 4, 2024
0915e99
Merge branch 'main' of github.com:cosmos/cosmos-sdk into aaronc/index…
aaronc Jun 4, 2024
c0207cc
define base package
aaronc Jun 4, 2024
8b6b68b
Merge branch 'aaronc/collections-expose-schema' into aaronc/indexer-wip
aaronc Jun 4, 2024
6fd52d6
Merge branch 'aaronc/collections-naming' into aaronc/indexer-wip
aaronc Jun 4, 2024
8230af4
indexer WIP
aaronc Jun 5, 2024
2a2f4bd
WIP
aaronc Jun 5, 2024
18a7949
WIP
aaronc Jun 6, 2024
e98b47c
refactoring
aaronc Jun 6, 2024
a708b0d
basic create table
aaronc Jun 6, 2024
d61c237
WIP on base
aaronc Jun 6, 2024
5428295
WIP on base
aaronc Jun 6, 2024
ce94453
receiving writes
aaronc Jun 6, 2024
4e5ff5d
receiving decodes
aaronc Jun 6, 2024
2bdd53e
simple decodes working
aaronc Jun 6, 2024
f95127a
creating tables
aaronc Jun 6, 2024
04e5360
basic indexing works
aaronc Jun 7, 2024
f496b79
distribution sort of works
aaronc Jun 7, 2024
82d7879
WIP
aaronc Jun 7, 2024
655cb7e
refactor Type -> Kind
aaronc Jun 10, 2024
76f6f32
feat: indexer base types
aaronc Jun 11, 2024
63aeb85
WIP on tests
aaronc Jun 11, 2024
28ed78b
feat(indexer/base): add Manager and DecodeableModule
aaronc Jun 11, 2024
21b787a
WIP
aaronc Jun 11, 2024
b2e57cd
update listener
aaronc Jun 12, 2024
2313851
docs
aaronc Jun 12, 2024
216e8f8
update listener
aaronc Jun 12, 2024
b65f3cd
feat(indexer): add listener test fixture
aaronc Jun 12, 2024
d8b6831
feat(indexer): postgres create table
aaronc Jun 12, 2024
6deca01
WIP
aaronc Jun 12, 2024
45d0bf7
Merge branch 'aaronc/indexer-base' into aaronc/indexer-wip
aaronc Jun 12, 2024
4a657d7
Merge branch 'main' of github.com:cosmos/cosmos-sdk into aaronc/index…
aaronc Jun 12, 2024
3c344b6
Merge branch 'aaronc/indexer-base-manager' into aaronc/indexer-wip
aaronc Jun 12, 2024
9e08c51
Merge branch 'aaronc/indexer-testing' into aaronc/indexer-wip
aaronc Jun 12, 2024
b5416a2
go.mod
aaronc Jun 12, 2024
4390b46
WIP
aaronc Jun 13, 2024
b9fb6c9
Merge branch 'main' of github.com:cosmos/cosmos-sdk into aaronc/index…
aaronc Jun 13, 2024
663ed17
rename column to field
aaronc Jun 13, 2024
4311357
delete code, simplify
aaronc Jun 13, 2024
c52655a
add error return
aaronc Jun 13, 2024
46669d3
remove ability to filter subscribed modules - this is a bit dangerous
aaronc Jun 13, 2024
0921977
Merge branch 'aaronc/indexer-base' into aaronc/indexer-testing
aaronc Jun 13, 2024
b7b6914
fixes
aaronc Jun 13, 2024
0a47c39
add docs about fields
aaronc Jun 13, 2024
0f07baf
updates
aaronc Jun 13, 2024
1cbe5bc
WIP
aaronc Jun 13, 2024
834a8f2
Merge branch 'aaronc/indexer-base' into aaronc/indexer-wip
aaronc Jun 13, 2024
3b90d5e
Merge branch 'aaronc/indexer-testing' into aaronc/indexer-wip
aaronc Jun 13, 2024
aacab9e
update table and entity language to object
aaronc Jun 13, 2024
7fd604f
update table and entity language to object
aaronc Jun 13, 2024
4130b32
WIP
aaronc Jun 13, 2024
e840496
rename to type
aaronc Jun 13, 2024
4a00094
rename to type
aaronc Jun 13, 2024
cff2b78
Merge branch 'aaronc/indexer-base' into aaronc/indexer-testing
aaronc Jun 13, 2024
e44dea2
spin out into its own go.mod
aaronc Jun 13, 2024
0c7f529
add CHANGELOG.md
aaronc Jun 13, 2024
d83b80a
Merge branch 'aaronc/indexer-base' into aaronc/indexer-testing
aaronc Jun 13, 2024
a94dd47
better faking
aaronc Jun 13, 2024
7990487
WIP
aaronc Jun 13, 2024
408ddc4
add DecodableModule interface
aaronc Jun 13, 2024
599e7cf
Merge branch 'main' of github.com:cosmos/cosmos-sdk into aaronc/index…
aaronc Jun 14, 2024
bc98756
make compatible with go 1.12
aaronc Jun 14, 2024
68d0afc
remove CommitCatchupSync - catch-up design in flux, may be premature …
aaronc Jun 17, 2024
2a52b97
Merge branch 'aaronc/indexer-base' into aaronc/indexer-postgres1
aaronc Jun 17, 2024
0c77dc3
Merge branch 'aaronc/indexer-base' into aaronc/indexer-testing
aaronc Jun 17, 2024
3398d06
Merge branch 'aaronc/indexer-testing' into aaronc/indexer-postgres1
aaronc Jun 17, 2024
f3a4832
create table
aaronc Jun 17, 2024
5403d9e
testing WIP
aaronc Jun 17, 2024
ba706a5
WIP
aaronc Jun 17, 2024
50a8c37
restore validation code
aaronc Jun 17, 2024
0a4b055
Merge branch 'aaronc/indexer-base-validation' into aaronc/indexer-pos…
aaronc Jun 17, 2024
f4de201
working create table
aaronc Jun 17, 2024
bf70e9d
updates
aaronc Jun 17, 2024
e2fcb60
Merge branch 'main' of github.com:cosmos/cosmos-sdk into aaronc/index…
aaronc Jun 17, 2024
6466ac5
updates
aaronc Jun 17, 2024
c87f020
updates
aaronc Jun 17, 2024
4c793d7
docs
aaronc Jun 18, 2024
dab02f7
Merge branch 'main' of github.com:cosmos/cosmos-sdk into aaronc/index…
aaronc Jun 18, 2024
3606a04
update validation
aaronc Jun 18, 2024
7cf9678
string tests
aaronc Jun 18, 2024
df3cde1
TestKindForGoValue
aaronc Jun 18, 2024
7c7ff79
update validation
aaronc Jun 18, 2024
2eb3ed2
WIP on TestField_Validate
aaronc Jun 18, 2024
8e2db24
simplifications
aaronc Jun 18, 2024
29d5a29
WIP updates
aaronc Jun 18, 2024
36aa92d
updates
aaronc Jun 18, 2024
aa73bd2
updates
aaronc Jun 18, 2024
160c186
update kind tests
aaronc Jun 18, 2024
00dceff
good kind test coverage
aaronc Jun 18, 2024
ccb9ca4
field tests and docs
aaronc Jun 18, 2024
df727e2
enum tests
aaronc Jun 18, 2024
842d420
object type tests
aaronc Jun 18, 2024
4b18658
object type docs
aaronc Jun 18, 2024
40b5d25
object type docs
aaronc Jun 18, 2024
6ed4d2b
revert comment changes
aaronc Jun 18, 2024
3ac7b0a
revert comment changes
aaronc Jun 18, 2024
8f3391b
simplify tests
aaronc Jun 18, 2024
e94e34a
Merge branch 'main' into aaronc/indexer-base-validation
aaronc Jun 18, 2024
2ba1d7c
Merge branch 'main' of github.com:cosmos/cosmos-sdk into aaronc/index…
aaronc Jun 18, 2024
1e1ffb7
refactor into standalone []Field validation methods
aaronc Jun 18, 2024
68771be
Merge branch 'main' into aaronc/indexer-base-validation
aaronc Jun 18, 2024
d116e23
rename
aaronc Jun 19, 2024
a5520b8
Merge remote-tracking branch 'origin/aaronc/indexer-base-validation' …
aaronc Jun 19, 2024
ad3f07a
revert
aaronc Jun 19, 2024
ff0ab4f
Merge branch 'aaronc/indexer-base-validation' into aaronc/indexer-wip
aaronc Jun 19, 2024
81658b1
Merge branch 'aaronc/indexer-postgres1' into aaronc/indexer-wip
aaronc Jun 19, 2024
42e024d
syncing
aaronc Jun 19, 2024
65b963e
tests pass again
aaronc Jun 19, 2024
9f30e1a
WIP
aaronc Jun 19, 2024
651aa19
WIP
aaronc Jun 19, 2024
93fdacc
Merge branch 'main' of github.com:cosmos/cosmos-sdk into aaronc/index…
aaronc Jun 19, 2024
0b6dfbd
add missing validation logic
aaronc Jun 19, 2024
7bcda06
Merge branch 'aaronc/indexer-base-validation' into aaronc/indexer-wip
aaronc Jun 19, 2024
6d400d3
Merge branch 'aaronc/indexer-testing' into aaronc/indexer-wip
aaronc Jun 19, 2024
bb019fd
WIP on testing
aaronc Jun 19, 2024
73342f8
WIP on testing
aaronc Jun 19, 2024
0520380
WIP on testing
aaronc Jun 19, 2024
c8bdedd
add name validation
aaronc Jun 19, 2024
0242018
name validation
aaronc Jun 19, 2024
85e5114
add name validation
aaronc Jun 19, 2024
aead85b
Merge branch 'aaronc/indexer-base-validation' into aaronc/indexer-wip
aaronc Jun 19, 2024
cec53c6
WIP on testing
aaronc Jun 19, 2024
c571d27
WIP on testing, graphql
aaronc Jun 19, 2024
9274402
WIP on testing
aaronc Jun 19, 2024
524ac3b
WIP on testing
aaronc Jun 19, 2024
2dc4226
WIP on testing
aaronc Jun 19, 2024
8af2478
fix naming
aaronc Jun 19, 2024
22a9b07
WIP on postgres insert/update
aaronc Jun 19, 2024
172cb5d
WIP on postgres insert/update
aaronc Jun 20, 2024
450723c
add Decimal and Integer restrictions
aaronc Jun 20, 2024
2ca77aa
Merge branch 'main' into aaronc/indexer-base-validation
aaronc Jun 20, 2024
693f8fb
gofumpt
aaronc Jun 20, 2024
9f4c1d0
Merge remote-tracking branch 'origin/aaronc/indexer-base-validation' …
aaronc Jun 20, 2024
870891a
Merge branch 'aaronc/indexer-base-validation' into aaronc/indexer-wip
aaronc Jun 20, 2024
8a9bb6b
feat(schema): break out new module from indexer/base
aaronc Jun 20, 2024
b40f2a4
update go.mods
aaronc Jun 20, 2024
6ecf0a4
Merge branch 'main' of github.com:cosmos/cosmos-sdk into aaronc/index…
aaronc Jun 20, 2024
f848bb7
Merge branch 'main' of github.com:cosmos/cosmos-sdk into aaronc/index…
aaronc Jun 20, 2024
8bb72cb
refactor indexerbase -> schema
aaronc Jun 20, 2024
07699c1
refactor testing
aaronc Jun 20, 2024
0c81f62
refactor(indexer/base): move to cosmossdk.io/schema, add ApplyUpdate …
aaronc Jun 20, 2024
43753bb
go mod tidy
aaronc Jun 20, 2024
d3a3cec
Merge branch 'aaronc/indexer-schema-refactor' into aaronc/indexer-wip
aaronc Jun 20, 2024
530e33b
Merge branch 'aaronc/indexer-base-manager' into aaronc/indexer-wip
aaronc Jun 20, 2024
d14d504
fixes
aaronc Jun 20, 2024
5c40659
WIP on testing
aaronc Jun 20, 2024
2211176
WIP on testing, indexer manager
aaronc Jun 20, 2024
b1e32d1
WIP on indexer manager
aaronc Jun 20, 2024
e067661
block data gen
aaronc Jun 20, 2024
384fabd
update postgres_test.go
aaronc Jun 20, 2024
8ba6c00
rework async
aaronc Jun 21, 2024
4e1082e
refactor Manager to LogicalDecoder
aaronc Jun 21, 2024
1a9820f
refactoring
aaronc Jun 21, 2024
1bc55b1
fix postgres init test
aaronc Jun 21, 2024
d571511
rename blockdata -> appdata
aaronc Jun 21, 2024
f40daee
partial test fixes
aaronc Jun 21, 2024
228da50
WIP on postgres testing
aaronc Jun 21, 2024
2094b42
make key fields not-null
aaronc Jun 21, 2024
831f678
insert, update, create fixes
aaronc Jun 21, 2024
d9deb05
WIP on delete, postgres fixes
aaronc Jun 21, 2024
04fb21a
renaming
aaronc Jun 21, 2024
db3ec49
WIP on debugging
aaronc Jun 21, 2024
a08051f
WIP on unique constraints, enum types, references
aaronc Jun 21, 2024
975ff27
WIP on references
aaronc Jun 21, 2024
51e5008
WIP on deletes
aaronc Jun 21, 2024
1144615
insert, update and delete working
aaronc Jun 21, 2024
97fbe42
WIP on retain deletions
aaronc Jun 21, 2024
17fa2b1
WIP on simulating test state
aaronc Jun 21, 2024
625b990
WIP on debugging
aaronc Jun 21, 2024
d9b63fe
fix update set issue
aaronc Jun 21, 2024
49fe938
retain deletions works
aaronc Jun 21, 2024
68bf92a
retain deletions works
aaronc Jun 21, 2024
562285d
WIP on testing updates
aaronc Jun 21, 2024
fbea108
check database state correctness
aaronc Jun 21, 2024
685ed46
check count
aaronc Jun 21, 2024
b4427fe
merge ValueUpdates
aaronc Jun 21, 2024
0e39126
simplify testing
aaronc Jun 21, 2024
e29f29b
test app
aaronc Jun 22, 2024
c8516d4
simple test graphql setup
aaronc Jun 22, 2024
281e19b
WIP on block, tx, event data
aaronc Jun 24, 2024
69c3791
collections WIP
aaronc Jun 24, 2024
16600e7
WIP on SDK updates
aaronc Jun 24, 2024
996feb6
Merge branch 'main' of github.com:cosmos/cosmos-sdk into aaronc/index…
aaronc Jun 24, 2024
7c90895
WIP on SDK updates
aaronc Jun 24, 2024
5f80b3b
WIP on fixing simapp build errors
aaronc Jun 24, 2024
9295e55
fixes to simapp build errors
aaronc Jun 24, 2024
a9cf0c6
WIP on indexer manager
aaronc Jun 25, 2024
bdb3431
fix build errors, add bech32 string support
aaronc Jul 1, 2024
9ab9634
fix dep cycles
aaronc Jul 1, 2024
21f9a8a
refactor to indexer API
aaronc Jul 1, 2024
a86682d
integrate manager into simapp
aaronc Jul 1, 2024
ab98ae5
WIP on simapp integration
aaronc Jul 1, 2024
facb977
Merge branch 'main' of github.com:cosmos/cosmos-sdk into aaronc/index…
aaronc Jul 1, 2024
2584c3a
Merge branch 'main' of github.com:cosmos/cosmos-sdk into aaronc/index…
aaronc Jul 2, 2024
8163efb
simapp integration WIP
aaronc Jul 2, 2024
cc29455
WIP on collections integration
aaronc Jul 2, 2024
1fb4d19
WIP on collections integration
aaronc Jul 2, 2024
08ffa8b
fixes
aaronc Jul 2, 2024
d025353
move listener wrapper to baseapp
aaronc Jul 2, 2024
a4b641e
refactor bech32
aaronc Jul 2, 2024
cbe6ff0
add comments
aaronc Jul 2, 2024
0f37771
Merge branch 'main' of github.com:cosmos/cosmos-sdk into aaronc/index…
aaronc Jul 5, 2024
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -63,3 +63,4 @@ debug_container.log
*.synctex.gz
/x/genutil/config/priv_validator_key.json
/x/genutil/data/priv_validator_state.json
.env.local
29 changes: 29 additions & 0 deletions baseapp/streaming.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import (

"github.com/spf13/cast"

"cosmossdk.io/schema/decoding"
"cosmossdk.io/schema/indexing"
"cosmossdk.io/store/streaming"
storetypes "cosmossdk.io/store/types"

Expand All @@ -22,6 +24,33 @@ const (
StreamingABCIStopNodeOnErrTomlKey = "stop-node-on-err"
)

func (app *BaseApp) EnableIndexer(indexerOpts interface{}, keys map[string]*storetypes.KVStoreKey, appModules map[string]any) error {
optsMap, ok := indexerOpts.(map[string]interface{})
if !ok {
return fmt.Errorf("invalid indexer options type %T, expected a map", indexerOpts)
}

listener, err := indexing.Start(indexing.Options{
Options: optsMap,
Resolver: decoding.ModuleSetDecoderResolver(appModules),
SyncSource: nil,
Logger: app.logger.With("module", "indexer"),
})
if err != nil {
return err
}

exposedKeys := exposeStoreKeysSorted([]string{"*"}, keys)
app.cms.AddListeners(exposedKeys)

app.streamingManager = storetypes.StreamingManager{
ABCIListeners: []storetypes.ABCIListener{storetypes.FromSchemaListener(listener)},
StopNodeOnErr: true,
}

return nil
}

// RegisterStreamingServices registers streaming services with the BaseApp.
func (app *BaseApp) RegisterStreamingServices(appOpts servertypes.AppOptions, keys map[string]*storetypes.KVStoreKey) error {
// register streaming services
Expand Down
85 changes: 85 additions & 0 deletions codec/collections.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
gogotypes "github.com/cosmos/gogoproto/types"
"google.golang.org/protobuf/encoding/protojson"
protov2 "google.golang.org/protobuf/proto"
"google.golang.org/protobuf/reflect/protoreflect"

"cosmossdk.io/schema"

Check failure on line 13 in codec/collections.go

View workflow job for this annotation

GitHub Actions / dependency-review

missing go.sum entry for module providing package cosmossdk.io/schema (imported by github.com/cosmos/cosmos-sdk/codec); to add:

Check failure on line 13 in codec/collections.go

View workflow job for this annotation

GitHub Actions / dependency-review

missing go.sum entry for module providing package cosmossdk.io/schema (imported by github.com/cosmos/cosmos-sdk/codec); to add:

Check failure on line 13 in codec/collections.go

View workflow job for this annotation

GitHub Actions / dependency-review

missing go.sum entry for module providing package cosmossdk.io/schema (imported by github.com/cosmos/cosmos-sdk/codec); to add:

Check failure on line 13 in codec/collections.go

View workflow job for this annotation

GitHub Actions / dependency-review

missing go.sum entry for module providing package cosmossdk.io/schema (imported by github.com/cosmos/cosmos-sdk/codec); to add:

Check failure on line 13 in codec/collections.go

View workflow job for this annotation

GitHub Actions / dependency-review

missing go.sum entry for module providing package cosmossdk.io/schema (imported by github.com/cosmos/cosmos-sdk/codec); to add:

Check failure on line 13 in codec/collections.go

View workflow job for this annotation

GitHub Actions / dependency-review

missing go.sum entry for module providing package cosmossdk.io/schema (imported by github.com/cosmos/cosmos-sdk/codec); to add:

"cosmossdk.io/collections"
collcodec "cosmossdk.io/collections/codec"
Expand Down Expand Up @@ -91,6 +94,16 @@
return "github.com/cosmos/gogoproto/" + c.messageName
}

func (c collValue[T, PT]) SchemaColumns() []schema.Field {
var pt PT
msgName := proto.MessageName(pt)
desc, err := proto.HybridResolver.FindDescriptorByName(protoreflect.FullName(msgName))
if err != nil {
panic(fmt.Errorf("could not find descriptor for %s: %w", msgName, err))
}
return protoCols(desc.(protoreflect.MessageDescriptor))
}

type protoMessageV2[T any] interface {
*T
protov2.Message
Expand Down Expand Up @@ -136,6 +149,11 @@
return "google.golang.org/protobuf/" + c.messageName
}

func (c collValue2[T, PT]) SchemaColumns() []schema.Field {
var pt PT
return protoCols(pt.ProtoReflect().Descriptor())
}

// CollInterfaceValue instantiates a new collections.ValueCodec for a generic
// interface value. The codec must be able to marshal and unmarshal the
// interface.
Expand Down Expand Up @@ -179,3 +197,70 @@
var t T
return fmt.Sprintf("%T", t)
}

func protoCols(desc protoreflect.MessageDescriptor) []schema.Field {
nFields := desc.Fields()
cols := make([]schema.Field, 0, nFields.Len())
for i := 0; i < nFields.Len(); i++ {
f := nFields.Get(i)
cols = append(cols, protoCol(f))
}
return cols
}

func protoCol(f protoreflect.FieldDescriptor) schema.Field {
col := schema.Field{Name: string(f.Name())}

if f.IsMap() || f.IsList() {
col.Kind = schema.JSONKind
col.Nullable = true
} else {
switch f.Kind() {
case protoreflect.BoolKind:
col.Kind = schema.BoolKind
case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind:
col.Kind = schema.Int32Kind
case protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind:
col.Kind = schema.Int64Kind
case protoreflect.Uint32Kind, protoreflect.Fixed32Kind:
col.Kind = schema.Int64Kind
case protoreflect.Uint64Kind, protoreflect.Fixed64Kind:
col.Kind = schema.IntegerStringKind
case protoreflect.FloatKind:
col.Kind = schema.Float32Kind
case protoreflect.DoubleKind:
col.Kind = schema.Float64Kind
case protoreflect.StringKind:
col.Kind = schema.StringKind
case protoreflect.BytesKind:
col.Kind = schema.BytesKind
case protoreflect.EnumKind:
col.Kind = schema.EnumKind
enumDesc := f.Enum()
var vals []string
n := enumDesc.Values().Len()
for i := 0; i < n; i++ {
vals = append(vals, string(enumDesc.Values().Get(i).Name()))
}
col.EnumDefinition = schema.EnumDefinition{
Name: string(enumDesc.Name()),
Values: vals,
}
case protoreflect.MessageKind:
col.Nullable = true
fullName := f.Message().FullName()
if fullName == "google.protobuf.Timestamp" {
col.Kind = schema.TimeKind
} else if fullName == "google.protobuf.Duration" {
col.Kind = schema.DurationKind
} else {
col.Kind = schema.JSONKind
}
}
if f.HasPresence() {
col.Nullable = true
}
}

return col
}
2 changes: 1 addition & 1 deletion collections/codec/alternative_value_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ type altValue struct {
func TestAltValueCodec(t *testing.T) {
// we assume we want to migrate the value from json(altValue) to just be
// the raw value uint64.
canonical := codec.KeyToValueCodec(codec.NewUint64Key[uint64]())
canonical := codec.KeyToValueCodec(codec.KeyCodec[uint64](codec.NewUint64Key[uint64]()))
alternative := func(v []byte) (uint64, error) {
var alt altValue
err := json.Unmarshal(v, &alt)
Expand Down
15 changes: 13 additions & 2 deletions collections/codec/bool.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@ import (
"strconv"
)

func NewBoolKey[T ~bool]() KeyCodec[T] { return boolKey[T]{} }
func NewBoolKey[T ~bool]() NameableKeyCodec[T] { return boolKey[T]{} }

type boolKey[T ~bool] struct{}
type boolKey[T ~bool] struct {
name string
}

func (b boolKey[T]) Encode(buffer []byte, key T) (int, error) {
if key {
Expand Down Expand Up @@ -64,3 +66,12 @@ func (b boolKey[T]) DecodeNonTerminal(buffer []byte) (int, T, error) {
func (b boolKey[T]) SizeNonTerminal(key T) int {
return b.Size(key)
}

func (b boolKey[T]) WithName(name string) NamedKeyCodec[T] {
b.name = name
return b
}

func (b boolKey[T]) Name() string {
return b.name
}
15 changes: 13 additions & 2 deletions collections/codec/bytes.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@ import (
// using the BytesKey KeyCodec.
const MaxBytesKeyNonTerminalSize = math.MaxUint8

func NewBytesKey[T ~[]byte]() KeyCodec[T] { return bytesKey[T]{} }
func NewBytesKey[T ~[]byte]() NameableKeyCodec[T] { return bytesKey[T]{} }

type bytesKey[T ~[]byte] struct{}
type bytesKey[T ~[]byte] struct {
name string
}

func (b bytesKey[T]) Encode(buffer []byte, key T) (int, error) {
return copy(buffer, key), nil
Expand Down Expand Up @@ -77,3 +79,12 @@ func (bytesKey[T]) DecodeNonTerminal(buffer []byte) (int, T, error) {
func (bytesKey[T]) SizeNonTerminal(key T) int {
return len(key) + 1
}

func (b bytesKey[T]) WithName(name string) NamedKeyCodec[T] {
b.name = name
return b
}

func (b bytesKey[T]) Name() string {
return b.name
}
18 changes: 18 additions & 0 deletions collections/codec/codec.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import (
"errors"
"fmt"

"cosmossdk.io/schema"

Check failure on line 7 in collections/codec/codec.go

View workflow job for this annotation

GitHub Actions / dependency-review

missing go.sum entry for module providing package cosmossdk.io/schema (imported by cosmossdk.io/x/bank); to add:

Check failure on line 7 in collections/codec/codec.go

View workflow job for this annotation

GitHub Actions / dependency-review

missing go.sum entry for module providing package cosmossdk.io/schema (imported by github.com/cosmos/cosmos-sdk/codec); to add:

Check failure on line 7 in collections/codec/codec.go

View workflow job for this annotation

GitHub Actions / dependency-review

missing go.sum entry for module providing package cosmossdk.io/schema (imported by cosmossdk.io/collections); to add:
)

var ErrEncoding = errors.New("collections: encoding error")
Expand Down Expand Up @@ -74,6 +76,22 @@
ValueType() string
}

// IndexableCodec is an interface that all codec's should implement in order to properly support indexing.
// It is not required by KeyCodec or ValueCodec in order to preserve backwards compatibility, but
// a future version of collections may make it required and all codec's should aim to implement it.
// If it is not implemented, fallback defaults will be used for indexing that may be sub-optimal.
//
// Implementations of IndexableCodec should test that they are conformant using the schema.ValidateWithKeyFields
// and schema.ValidateWithValueFields depending on whether the codec is a KeyCodec or ValueCodec respectively.
type IndexableCodec interface {
LogicalDecoder() LogicalDecoder
}

type LogicalDecoder struct {
Fields []schema.Field
Decode func([]byte) (any, error)
}

// NewUntypedValueCodec returns an UntypedValueCodec for the provided ValueCodec.
func NewUntypedValueCodec[V any](v ValueCodec[V]) UntypedValueCodec {
typeName := fmt.Sprintf("%T", *new(V))
Expand Down
30 changes: 26 additions & 4 deletions collections/codec/int.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@ import (
"strconv"
)

func NewInt64Key[T ~int64]() KeyCodec[T] { return int64Key[T]{} }
func NewInt64Key[T ~int64]() NameableKeyCodec[T] { return int64Key[T]{} }

type int64Key[T ~int64] struct{}
type int64Key[T ~int64] struct {
name string
}

func (i int64Key[T]) Encode(buffer []byte, key T) (int, error) {
binary.BigEndian.PutUint64(buffer, (uint64)(key))
Expand Down Expand Up @@ -64,11 +66,22 @@ func (i int64Key[T]) SizeNonTerminal(_ T) int {
return 8
}

func NewInt32Key[T ~int32]() KeyCodec[T] {
func (i int64Key[T]) WithName(name string) NamedKeyCodec[T] {
i.name = name
return i
}

func (i int64Key[T]) Name() string {
return i.name
}

func NewInt32Key[T ~int32]() NameableKeyCodec[T] {
return int32Key[T]{}
}

type int32Key[T ~int32] struct{}
type int32Key[T ~int32] struct {
name string
}

func (i int32Key[T]) Encode(buffer []byte, key T) (int, error) {
binary.BigEndian.PutUint32(buffer, (uint32)(key))
Expand Down Expand Up @@ -121,3 +134,12 @@ func (i int32Key[T]) DecodeNonTerminal(buffer []byte) (int, T, error) {
func (i int32Key[T]) SizeNonTerminal(_ T) int {
return 4
}

func (i int32Key[T]) WithName(name string) NamedKeyCodec[T] {
i.name = name
return i
}

func (i int32Key[T]) Name() string {
return i.name
}
35 changes: 35 additions & 0 deletions collections/codec/naming.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package codec

type HasName interface {
// Name returns the name of key in the schema if one is defined or the empty string.
// Multipart keys should separate names with commas, i.e. "name1,name2".
Name() string
}

// NameableKeyCodec is a KeyCodec that can be named.
type NameableKeyCodec[T any] interface {
KeyCodec[T]

// WithName returns the KeyCodec with the provided name.
WithName(name string) NamedKeyCodec[T]
}

// NamedKeyCodec is a KeyCodec that has a name.
type NamedKeyCodec[T any] interface {
KeyCodec[T]
HasName
}

// NameableValueCodec is a ValueCodec that can be named.
type NameableValueCodec[T any] interface {
ValueCodec[T]

// WithName returns the ValueCodec with the provided name.
WithName(name string) NamedValueCodec[T]
}

// NamedValueCodec is a ValueCodec that has a name.
type NamedValueCodec[T any] interface {
ValueCodec[T]
HasName
}
15 changes: 13 additions & 2 deletions collections/codec/string.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,16 @@ import (
"fmt"
)

func NewStringKeyCodec[T ~string]() KeyCodec[T] { return stringKey[T]{} }
func NewStringKeyCodec[T ~string]() NameableKeyCodec[T] { return stringKey[T]{} }

const (
// StringDelimiter defines the delimiter of a string key when used in non-terminal encodings.
StringDelimiter uint8 = 0x0
)

type stringKey[T ~string] struct{}
type stringKey[T ~string] struct {
name string
}

func (stringKey[T]) Encode(buffer []byte, key T) (int, error) {
return copy(buffer, key), nil
Expand Down Expand Up @@ -66,3 +68,12 @@ func (stringKey[T]) Stringify(key T) string {
func (stringKey[T]) KeyType() string {
return "string"
}

func (s stringKey[T]) WithName(name string) NamedKeyCodec[T] {
s.name = name
return s
}

func (s stringKey[T]) Name() string {
return s.name
}
Loading
Loading