diff --git a/.github/ISSUE_TEMPLATE/module-readiness-checklist.md b/.github/ISSUE_TEMPLATE/module-readiness-checklist.md index 4e6bebed90c2..7892e356bcf6 100644 --- a/.github/ISSUE_TEMPLATE/module-readiness-checklist.md +++ b/.github/ISSUE_TEMPLATE/module-readiness-checklist.md @@ -16,7 +16,7 @@ The module **should not** be included in any Release Candidate tag until it has - [ ] API audit (at least 1 person) (@assignee) - [ ] Are Msg and Query methods and types well-named and organized? - - [ ] Is everything well documented (inline godoc as well as the spec [README.md](https://github.com/cosmos/cosmos-sdk/blob/main/docs/spec/SPEC-SPEC.md) in module directory) + - [ ] Is everything well documented (inline godoc as well as the spec [README.md](https://github.com/cosmos/cosmos-sdk/blob/main/docs/spec/README.md) in module directory) - [ ] State machine audit (at least 2 people) (@assignee1, @assignee2) - [ ] Read through MsgServer code and verify correctness upon visual inspection - [ ] Ensure all state machine code which could be confusing is properly commented diff --git a/baseapp/streaming.go b/baseapp/streaming.go index c978d959aa7c..9c5c3d5d1742 100644 --- a/baseapp/streaming.go +++ b/baseapp/streaming.go @@ -1,12 +1,18 @@ package baseapp import ( + "context" "fmt" "sort" "strings" + abci "github.com/cometbft/cometbft/api/cometbft/abci/v1" "github.com/spf13/cast" + "cosmossdk.io/schema" + "cosmossdk.io/schema/appdata" + "cosmossdk.io/schema/decoding" + "cosmossdk.io/schema/indexer" "cosmossdk.io/store/streaming" storetypes "cosmossdk.io/store/types" @@ -22,6 +28,31 @@ const ( StreamingABCIStopNodeOnErrTomlKey = "stop-node-on-err" ) +// EnableIndexer enables the built-in indexer with the provided options (usually from the app.toml indexer key), +// kv-store keys, and app modules. Using the built-in indexer framework is mutually exclusive from using other +// types of streaming listeners. +func (app *BaseApp) EnableIndexer(indexerOpts interface{}, keys map[string]*storetypes.KVStoreKey, appModules map[string]any) error { + listener, err := indexer.StartManager(indexer.ManagerOptions{ + Config: indexerOpts, + 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{listenerWrapper{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 @@ -110,3 +141,51 @@ func exposeStoreKeysSorted(keysStr []string, keys map[string]*storetypes.KVStore return exposeStoreKeys } + +type listenerWrapper struct { + listener appdata.Listener +} + +func (p listenerWrapper) ListenFinalizeBlock(_ context.Context, req abci.FinalizeBlockRequest, res abci.FinalizeBlockResponse) error { + if p.listener.StartBlock != nil { + err := p.listener.StartBlock(appdata.StartBlockData{ + Height: uint64(req.Height), + }) + if err != nil { + return err + } + } + + //// TODO txs, events + + return nil +} + +func (p listenerWrapper) ListenCommit(ctx context.Context, res abci.CommitResponse, changeSet []*storetypes.StoreKVPair) error { + if cb := p.listener.OnKVPair; cb != nil { + updates := make([]appdata.ModuleKVPairUpdate, len(changeSet)) + for i, pair := range changeSet { + updates[i] = appdata.ModuleKVPairUpdate{ + ModuleName: pair.StoreKey, + Update: schema.KVPairUpdate{ + Key: pair.Key, + Value: pair.Value, + Delete: pair.Delete, + }, + } + } + err := cb(appdata.KVPairData{Updates: updates}) + if err != nil { + return err + } + } + + if p.listener.Commit != nil { + err := p.listener.Commit(appdata.CommitData{}) + if err != nil { + return err + } + } + + return nil +} diff --git a/client/v2/go.mod b/client/v2/go.mod index 97c1c76d7852..8b3377649cb9 100644 --- a/client/v2/go.mod +++ b/client/v2/go.mod @@ -170,7 +170,10 @@ require ( pgregory.net/rapid v1.1.0 // indirect ) -require github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect +require ( + cosmossdk.io/schema v0.1.1 // indirect + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect +) replace github.com/cosmos/cosmos-sdk => ./../../ diff --git a/client/v2/go.sum b/client/v2/go.sum index 9430fc0c6a26..1bf49b633329 100644 --- a/client/v2/go.sum +++ b/client/v2/go.sum @@ -10,6 +10,8 @@ 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/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE= cosmossdk.io/math v1.3.0/go.mod h1:vnRTxewy+M7BtXBNFybkuhSH4WfedVAAnERHgVFhp3k= +cosmossdk.io/schema v0.1.1 h1:I0M6pgI7R10nq+/HCQfbO6BsGBZA8sQy+duR1Y3aKcA= +cosmossdk.io/schema v0.1.1/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMbk2FiG/kXiLl8BRyzTWDw7gX/Hz7Dd5eDMs= diff --git a/docs/architecture/adr-014-proportional-slashing.md b/docs/architecture/adr-014-proportional-slashing.md index 976136a9f59f..d9aeffb80c6a 100644 --- a/docs/architecture/adr-014-proportional-slashing.md +++ b/docs/architecture/adr-014-proportional-slashing.md @@ -65,7 +65,7 @@ Whenever a new slash occurs, a `SlashEvent` struct is created with the faulting We then will iterate over all the SlashEvents in the queue, adding their `ValidatorVotingPercent` to calculate the new percent to slash all the validators in the queue at, using the "Square of Sum of Roots" formula introduced above. -Once we have the `NewSlashPercent`, we then iterate over all the `SlashEvent`s in the queue once again, and if `NewSlashPercent > SlashedSoFar` for that SlashEvent, we call the `staking.Slash(slashEvent.Address, slashEvent.Power, Math.Min(Math.Max(minSlashPercent, NewSlashPercent - SlashedSoFar), maxSlashPercent)` (we pass in the power of the validator before any slashes occurred, so that we slash the right amount of tokens). We then set `SlashEvent.SlashedSoFar` amount to `NewSlashPercent`. +Once we have the `NewSlashPercent`, we then iterate over all the `SlashEvent`s in the queue once again, and if `NewSlashPercent > SlashedSoFar` for that SlashEvent, we call the `staking.Slash(slashEvent.Address, slashEvent.Power, Math.Min(Math.Max(minSlashPercent, NewSlashPercent - SlashedSoFar), maxSlashPercent))` (we pass in the power of the validator before any slashes occurred, so that we slash the right amount of tokens). We then set `SlashEvent.SlashedSoFar` amount to `NewSlashPercent`. ## Status diff --git a/docs/architecture/adr-039-epoched-staking.md b/docs/architecture/adr-039-epoched-staking.md index c343ac514f5b..bfdddbe209b3 100644 --- a/docs/architecture/adr-039-epoched-staking.md +++ b/docs/architecture/adr-039-epoched-staking.md @@ -21,7 +21,7 @@ This ADR updates the proof of stake module to buffer the staking weight updates The current proof of stake module takes the design decision to apply staking weight changes to the consensus engine immediately. This means that delegations and unbonds get applied immediately to the validator set. This decision was primarily done as it was implementationally simplest, and because we at the time believed that this would lead to better UX for clients. -An alternative design choice is to allow buffering staking updates (delegations, unbonds, validators joining) for a number of blocks. This 'epoch'd proof of stake consensus provides the guarantee that the consensus weights for validators will not change mid-epoch, except in the event of a slash condition. +An alternative design choice is to allow buffering staking updates (delegations, unbonds, validators joining) for a number of blocks. This 'epoch'ed proof of stake consensus provides the guarantee that the consensus weights for validators will not change mid-epoch, except in the event of a slash condition. Additionally, the UX hurdle may not be as significant as was previously thought. This is because it is possible to provide users immediate acknowledgement that their bond was recorded and will be executed. diff --git a/docs/architecture/adr-049-state-sync-hooks.md b/docs/architecture/adr-049-state-sync-hooks.md index 3fb0b1850532..50c551ea2b8d 100644 --- a/docs/architecture/adr-049-state-sync-hooks.md +++ b/docs/architecture/adr-049-state-sync-hooks.md @@ -139,7 +139,7 @@ type ExtensionSnapshotter interface { ## Consequences -As a result of this implementation, we are able to create snapshots of binary chunk stream for the state that we maintain outside of the IAVL Tree, CosmWasm blobs for example. And new clients are able to fetch sanpshots of state for all modules that have implemented the corresponding interface from peer nodes. +As a result of this implementation, we are able to create snapshots of binary chunk stream for the state that we maintain outside of the IAVL Tree, CosmWasm blobs for example. And new clients are able to fetch snapshots of state for all modules that have implemented the corresponding interface from peer nodes. ### Backwards Compatibility diff --git a/docs/build/building-modules/11-structure.md b/docs/build/building-modules/11-structure.md index 6b66f5380648..95750c4e4867 100644 --- a/docs/build/building-modules/11-structure.md +++ b/docs/build/building-modules/11-structure.md @@ -50,29 +50,29 @@ x/{module_name} │   ├── keys.go │   ├── msg_server.go │   └── querier.go -├── module -│   └── module.go -│   └── abci.go -│   └── autocli.go -│   └── depinject.go ├── simulation │   ├── decoder.go │   ├── genesis.go │   ├── operations.go │   └── params.go -├── {module_name}.pb.go -├── codec.go -├── errors.go -├── events.go -├── events.pb.go -├── expected_keepers.go -├── genesis.go -├── genesis.pb.go -├── keys.go -├── msgs.go -├── params.go -├── query.pb.go -├── tx.pb.go +├── types +│   ├── {module_name}.pb.go +│ ├── codec.go +│ ├── errors.go +│ ├── events.go +│ ├── events.pb.go +│ ├── expected_keepers.go +│ ├── genesis.go +│ ├── genesis.pb.go +│ ├── keys.go +│ ├── msgs.go +│ ├── params.go +│ ├── query.pb.go +│ └── tx.pb.go +├── module.go +├── abci.go +├── autocli.go +├── depinject.go └── README.md ``` @@ -80,11 +80,9 @@ x/{module_name} * `exported/`: The module's exported types - typically interface types. If a module relies on keepers from another module, it is expected to receive the keepers as interface contracts through the `expected_keepers.go` file (see below) in order to avoid a direct dependency on the module implementing the keepers. However, these interface contracts can define methods that operate on and/or return types that are specific to the module that is implementing the keepers and this is where `exported/` comes into play. The interface types that are defined in `exported/` use canonical types, allowing for the module to receive the keepers as interface contracts through the `expected_keepers.go` file. This pattern allows for code to remain DRY and also alleviates import cycle chaos. * `keeper/`: The module's `Keeper` and `MsgServer` implementation. * `abci.go`: The module's `BeginBlocker` and `EndBlocker` implementations (this file is only required if `BeginBlocker` and/or `EndBlocker` need to be defined). -* `module/`: The module's `AppModule` implementation. - * `autocli.go`: The module [autocli](https://docs.cosmos.network/main/core/autocli) options. * `simulation/`: The module's [simulation](./14-simulator.md) package defines functions used by the blockchain simulator application (`simapp`). * `README.md`: The module's specification documents outlining important concepts, state storage structure, and message and event type definitions. Learn more how to write module specs in the [spec guidelines](../spec/SPEC_MODULE.md). -* The root directory includes type definitions for messages, events, and genesis state, including the type definitions generated by Protocol Buffers. +* `types/`: includes type definitions for messages, events, and genesis state, including the type definitions generated by Protocol Buffers. * `codec.go`: The module's registry methods for interface types. * `errors.go`: The module's sentinel errors. * `events.go`: The module's event types and constructors. @@ -94,3 +92,8 @@ x/{module_name} * `msgs.go`: The module's message type definitions and associated methods. * `params.go`: The module's parameter type definitions and associated methods. * `*.pb.go`: The module's type definitions generated by Protocol Buffers (as defined in the respective `*.proto` files above). +* The root directory includes the module's `AppModule` implementation. + * `autocli.go`: The module [autocli](https://docs.cosmos.network/main/core/autocli) options. + * `depinject.go`: The module [depinject](./15-depinject.md#type-definition) options. + +> Note: although the above pattern is followed by most of the Cosmos SDK modules, there are some modules that don't follow this pattern. E.g `x/group` and `x/nft` dont have a `types` folder, instead all of the type definitions for messages, events, and genesis state are live in the root directory and the module's `AppModule` implementation lives in the `module` folder. diff --git a/go.mod b/go.mod index c78efc9c329e..bba738c8a342 100644 --- a/go.mod +++ b/go.mod @@ -11,6 +11,7 @@ require ( cosmossdk.io/errors v1.0.1 cosmossdk.io/log v1.3.1 cosmossdk.io/math v1.3.0 + cosmossdk.io/schema v0.1.1 cosmossdk.io/store v1.1.1-0.20240418092142-896cdf1971bc cosmossdk.io/x/auth v0.0.0-00010101000000-000000000000 cosmossdk.io/x/bank v0.0.0-20240226161501-23359a0b6d91 diff --git a/go.sum b/go.sum index 6270dd330537..d3bee7ec0a2d 100644 --- a/go.sum +++ b/go.sum @@ -8,6 +8,8 @@ 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/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE= cosmossdk.io/math v1.3.0/go.mod h1:vnRTxewy+M7BtXBNFybkuhSH4WfedVAAnERHgVFhp3k= +cosmossdk.io/schema v0.1.1 h1:I0M6pgI7R10nq+/HCQfbO6BsGBZA8sQy+duR1Y3aKcA= +cosmossdk.io/schema v0.1.1/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMbk2FiG/kXiLl8BRyzTWDw7gX/Hz7Dd5eDMs= diff --git a/schema/decoding/resolver.go b/schema/decoding/resolver.go new file mode 100644 index 000000000000..db0ec0bb1726 --- /dev/null +++ b/schema/decoding/resolver.go @@ -0,0 +1,66 @@ +package decoding + +import ( + "sort" + + "cosmossdk.io/schema" +) + +// DecoderResolver is an interface that allows indexers to discover and use module decoders. +type DecoderResolver interface { + // IterateAll iterates over all available module decoders. + IterateAll(func(moduleName string, cdc schema.ModuleCodec) error) error + + // LookupDecoder looks up a specific module decoder. + LookupDecoder(moduleName string) (decoder schema.ModuleCodec, found bool, err error) +} + +// ModuleSetDecoderResolver returns DecoderResolver that will discover modules implementing +// DecodeableModule in the provided module set. +func ModuleSetDecoderResolver(moduleSet map[string]interface{}) DecoderResolver { + return &moduleSetDecoderResolver{ + moduleSet: moduleSet, + } +} + +type moduleSetDecoderResolver struct { + moduleSet map[string]interface{} +} + +func (a moduleSetDecoderResolver) IterateAll(f func(string, schema.ModuleCodec) error) error { + keys := make([]string, 0, len(a.moduleSet)) + for k := range a.moduleSet { + keys = append(keys, k) + } + sort.Strings(keys) + for _, k := range keys { + module := a.moduleSet[k] + dm, ok := module.(schema.HasModuleCodec) + if ok { + decoder, err := dm.ModuleCodec() + if err != nil { + return err + } + err = f(k, decoder) + if err != nil { + return err + } + } + } + return nil +} + +func (a moduleSetDecoderResolver) LookupDecoder(moduleName string) (schema.ModuleCodec, bool, error) { + mod, ok := a.moduleSet[moduleName] + if !ok { + return schema.ModuleCodec{}, false, nil + } + + dm, ok := mod.(schema.HasModuleCodec) + if !ok { + return schema.ModuleCodec{}, false, nil + } + + decoder, err := dm.ModuleCodec() + return decoder, true, err +} diff --git a/schema/decoding/resolver_test.go b/schema/decoding/resolver_test.go new file mode 100644 index 000000000000..ecea614d1999 --- /dev/null +++ b/schema/decoding/resolver_test.go @@ -0,0 +1,124 @@ +package decoding + +import ( + "fmt" + "testing" + + "cosmossdk.io/schema" +) + +type modA struct{} + +func (m modA) ModuleCodec() (schema.ModuleCodec, error) { + return schema.ModuleCodec{ + Schema: schema.ModuleSchema{ObjectTypes: []schema.ObjectType{{Name: "A"}}}, + }, nil +} + +type modB struct{} + +func (m modB) ModuleCodec() (schema.ModuleCodec, error) { + return schema.ModuleCodec{ + Schema: schema.ModuleSchema{ObjectTypes: []schema.ObjectType{{Name: "B"}}}, + }, nil +} + +type modC struct{} + +var moduleSet = map[string]interface{}{ + "modA": modA{}, + "modB": modB{}, + "modC": modC{}, +} + +var resolver = ModuleSetDecoderResolver(moduleSet) + +func TestModuleSetDecoderResolver_IterateAll(t *testing.T) { + objectTypes := map[string]bool{} + err := resolver.IterateAll(func(moduleName string, cdc schema.ModuleCodec) error { + objectTypes[cdc.Schema.ObjectTypes[0].Name] = true + return nil + }) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + if len(objectTypes) != 2 { + t.Fatalf("expected 2 object types, got %d", len(objectTypes)) + } + + if !objectTypes["A"] { + t.Fatalf("expected object type A") + } + + if !objectTypes["B"] { + t.Fatalf("expected object type B") + } +} + +func TestModuleSetDecoderResolver_LookupDecoder(t *testing.T) { + decoder, found, err := resolver.LookupDecoder("modA") + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + if !found { + t.Fatalf("expected to find decoder for modA") + } + + if decoder.Schema.ObjectTypes[0].Name != "A" { + t.Fatalf("expected object type A, got %s", decoder.Schema.ObjectTypes[0].Name) + } + + decoder, found, err = resolver.LookupDecoder("modB") + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + if !found { + t.Fatalf("expected to find decoder for modB") + } + + if decoder.Schema.ObjectTypes[0].Name != "B" { + t.Fatalf("expected object type B, got %s", decoder.Schema.ObjectTypes[0].Name) + } + + decoder, found, err = resolver.LookupDecoder("modC") + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + if found { + t.Fatalf("expected not to find decoder") + } + + decoder, found, err = resolver.LookupDecoder("modD") + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + if found { + t.Fatalf("expected not to find decoder") + } +} + +type modD struct{} + +func (m modD) ModuleCodec() (schema.ModuleCodec, error) { + return schema.ModuleCodec{}, fmt.Errorf("an error") +} + +func TestModuleSetDecoderResolver_IterateAll_Error(t *testing.T) { + resolver := ModuleSetDecoderResolver(map[string]interface{}{ + "modD": modD{}, + }) + err := resolver.IterateAll(func(moduleName string, cdc schema.ModuleCodec) error { + if moduleName == "modD" { + t.Fatalf("expected error") + } + return nil + }) + if err == nil { + t.Fatalf("expected error") + } +} diff --git a/schema/decoding/sync.go b/schema/decoding/sync.go new file mode 100644 index 000000000000..85e6b4d74ba0 --- /dev/null +++ b/schema/decoding/sync.go @@ -0,0 +1,8 @@ +package decoding + +// SyncSource is an interface that allows indexers to start indexing modules with pre-existing state. +// It should generally be a wrapper around the key-value store. +type SyncSource interface { + // IterateAllKVPairs iterates over all key-value pairs for a given module. + IterateAllKVPairs(moduleName string, fn func(key, value []byte) error) error +} diff --git a/schema/indexer/README.md b/schema/indexer/README.md new file mode 100644 index 000000000000..9fdec6753a27 --- /dev/null +++ b/schema/indexer/README.md @@ -0,0 +1,15 @@ +# Indexer Framework + +# Defining an Indexer + +Indexer implementations should be registered with the `indexer.Register` function with a unique type name. Indexers take the configuration options defined by `indexer.Config` which defines a common set of configuration options as well as indexer-specific options under the `config` sub-key. Indexers do not need to manage the common filtering options specified in `Config` - the indexer manager will manage these for the indexer. Indexer implementations just need to return a correct `InitResult` response. + +# Integrating the Indexer Manager + +The indexer manager should be used for managing all indexers and should be integrated directly with applications wishing to support indexing. The `StartManager` function is used to start the manager. The configuration options for the manager and all indexer targets should be passed as the ManagerOptions.Config field and should match the json structure of ManagerConfig. An example configuration section in `app.toml` might look like this: + +```toml +[indexer.target.postgres] +type = "postgres" +config.database_url = "postgres://user:password@localhost:5432/dbname" +``` diff --git a/schema/indexer/indexer.go b/schema/indexer/indexer.go new file mode 100644 index 000000000000..ba3d0db704fa --- /dev/null +++ b/schema/indexer/indexer.go @@ -0,0 +1,78 @@ +package indexer + +import ( + "context" + + "cosmossdk.io/schema/appdata" + "cosmossdk.io/schema/logutil" +) + +// Config species the configuration passed to an indexer initialization function. +// It includes both common configuration options related to include or excluding +// parts of the data stream as well as indexer specific options under the config +// subsection. +// +// NOTE: it is an error for an indexer to change its common options, such as adding +// or removing indexed modules, after the indexer has been initialized because this +// could result in an inconsistent state. +type Config struct { + // Type is the name of the indexer type as registered with Register. + Type string `json:"type"` + + // Config are the indexer specific config options specified by the user. + Config map[string]interface{} `json:"config"` + + // ExcludeState specifies that the indexer will not receive state updates. + ExcludeState bool `json:"exclude_state"` + + // ExcludeEvents specifies that the indexer will not receive events. + ExcludeEvents bool `json:"exclude_events"` + + // ExcludeTxs specifies that the indexer will not receive transaction's. + ExcludeTxs bool `json:"exclude_txs"` + + // ExcludeBlockHeaders specifies that the indexer will not receive block headers, + // although it will still receive StartBlock and Commit callbacks, just without + // the header data. + ExcludeBlockHeaders bool `json:"exclude_block_headers"` + + // IncludeModules specifies a list of modules whose state the indexer will + // receive state updates for. + // Only one of include or exclude modules should be specified. + IncludeModules []string `json:"include_modules"` + + // ExcludeModules specifies a list of modules whose state the indexer will not + // receive state updates for. + // Only one of include or exclude modules should be specified. + ExcludeModules []string `json:"exclude_modules"` +} + +type InitFunc = func(InitParams) (InitResult, error) + +// InitParams is the input to the indexer initialization function. +type InitParams struct { + // Config is the indexer config. + Config Config + + // Context is the context that the indexer should use to listen for a shutdown signal via Context.Done(). Other + // parameters may also be passed through context from the app if necessary. + Context context.Context + + // Logger is a logger the indexer can use to write log messages. + Logger logutil.Logger +} + +// InitResult is the indexer initialization result and includes the indexer's listener implementation. +type InitResult struct { + // Listener is the indexer's app data listener. + Listener appdata.Listener + + // LastBlockPersisted indicates the last block that the indexer persisted (if it is persisting data). It + // should be 0 if the indexer has no data stored and wants to start syncing state. It should be -1 if the indexer + // does not care to persist state at all and is just listening for some other streaming purpose. If the indexer + // has persisted state and has missed some blocks, a runtime error will occur to prevent the indexer from continuing + // in an invalid state. If an indexer starts indexing after a chain's genesis (returning 0), the indexer manager + // will attempt to perform a catch-up sync of state. Historical events will not be replayed, but an accurate + // representation of the current state at the height at which indexing began can be reproduced. + LastBlockPersisted int64 +} diff --git a/schema/indexer/manager.go b/schema/indexer/manager.go new file mode 100644 index 000000000000..5a7e39faad0a --- /dev/null +++ b/schema/indexer/manager.go @@ -0,0 +1,44 @@ +package indexer + +import ( + "context" + + "cosmossdk.io/schema/appdata" + "cosmossdk.io/schema/decoding" + "cosmossdk.io/schema/logutil" +) + +// ManagerOptions are the options for starting the indexer manager. +type ManagerOptions struct { + // Config is the user configuration for all indexing. It should generally be an instance of map[string]interface{} + // and match the json structure of ManagerConfig. The manager will attempt to convert it to ManagerConfig. + Config interface{} + + // Resolver is the decoder resolver that will be used to decode the data. It is required. + Resolver decoding.DecoderResolver + + // SyncSource is a representation of the current state of key-value data to be used in a catch-up sync. + // Catch-up syncs will be performed at initialization when necessary. SyncSource is optional but if + // it is omitted, indexers will only be able to start indexing state from genesis. + SyncSource decoding.SyncSource + + // Logger is the logger that indexers can use to write logs. It is optional. + Logger logutil.Logger + + // Context is the context that indexers should use for shutdown signals via Context.Done(). It can also + // be used to pass down other parameters to indexers if necessary. If it is omitted, context.Background + // will be used. + Context context.Context +} + +// ManagerConfig is the configuration of the indexer manager and contains the configuration for each indexer target. +type ManagerConfig struct { + // Target is a map of named indexer targets to their configuration. + Target map[string]Config +} + +// StartManager starts the indexer manager with the given options. The state machine should write all relevant app data to +// the returned listener. +func StartManager(opts ManagerOptions) (appdata.Listener, error) { + panic("TODO: this will be implemented in a follow-up PR, this function is just a stub to demonstrate the API") +} diff --git a/schema/indexer/registry.go b/schema/indexer/registry.go new file mode 100644 index 000000000000..445f56876add --- /dev/null +++ b/schema/indexer/registry.go @@ -0,0 +1,14 @@ +package indexer + +import "fmt" + +// Register registers an indexer type with the given initialization function. +func Register(indexerType string, initFunc InitFunc) { + if _, ok := indexerRegistry[indexerType]; ok { + panic(fmt.Sprintf("indexer %s already registered", indexerType)) + } + + indexerRegistry[indexerType] = initFunc +} + +var indexerRegistry = map[string]InitFunc{} diff --git a/schema/indexer/registry_test.go b/schema/indexer/registry_test.go new file mode 100644 index 000000000000..b9f46910c8fd --- /dev/null +++ b/schema/indexer/registry_test.go @@ -0,0 +1,26 @@ +package indexer + +import "testing" + +func TestRegister(t *testing.T) { + Register("test", func(params InitParams) (InitResult, error) { + return InitResult{}, nil + }) + + if indexerRegistry["test"] == nil { + t.Fatalf("expected to find indexer") + } + + if indexerRegistry["test2"] != nil { + t.Fatalf("expected not to find indexer") + } + + defer func() { + if r := recover(); r == nil { + t.Fatalf("expected to panic") + } + }() + Register("test", func(params InitParams) (InitResult, error) { + return InitResult{}, nil + }) +} diff --git a/schema/logutil/logger.go b/schema/logutil/logger.go new file mode 100644 index 000000000000..cb6b34ebfd2b --- /dev/null +++ b/schema/logutil/logger.go @@ -0,0 +1,35 @@ +// Package logutil defines the Logger interface expected by indexer implementations. +// It is implemented by cosmossdk.io/log which is not imported to minimize dependencies. +package logutil + +// Logger is the logger interface expected by indexer implementations. +type Logger interface { + // Info takes a message and a set of key/value pairs and logs with level INFO. + // The key of the tuple must be a string. + Info(msg string, keyVals ...interface{}) + + // Warn takes a message and a set of key/value pairs and logs with level WARN. + // The key of the tuple must be a string. + Warn(msg string, keyVals ...interface{}) + + // Error takes a message and a set of key/value pairs and logs with level ERR. + // The key of the tuple must be a string. + Error(msg string, keyVals ...interface{}) + + // Debug takes a message and a set of key/value pairs and logs with level DEBUG. + // The key of the tuple must be a string. + Debug(msg string, keyVals ...interface{}) +} + +// NoopLogger is a logger that doesn't do anything. +type NoopLogger struct{} + +func (n NoopLogger) Info(string, ...interface{}) {} + +func (n NoopLogger) Warn(string, ...interface{}) {} + +func (n NoopLogger) Error(string, ...interface{}) {} + +func (n NoopLogger) Debug(string, ...interface{}) {} + +var _ Logger = NoopLogger{} diff --git a/server/v2/cometbft/go.mod b/server/v2/cometbft/go.mod index 6e3509c7c406..ad6a2c2e23b7 100644 --- a/server/v2/cometbft/go.mod +++ b/server/v2/cometbft/go.mod @@ -53,6 +53,7 @@ require ( cosmossdk.io/depinject v1.0.0-alpha.4 // indirect cosmossdk.io/log v1.3.1 // indirect cosmossdk.io/math v1.3.0 // indirect + cosmossdk.io/schema v0.1.1 // indirect cosmossdk.io/store v1.1.1-0.20240418092142-896cdf1971bc // indirect cosmossdk.io/x/bank v0.0.0-20240226161501-23359a0b6d91 // indirect cosmossdk.io/x/staking v0.0.0-00010101000000-000000000000 // indirect diff --git a/server/v2/cometbft/go.sum b/server/v2/cometbft/go.sum index 19d5bab44988..a2f2f6f68341 100644 --- a/server/v2/cometbft/go.sum +++ b/server/v2/cometbft/go.sum @@ -10,6 +10,8 @@ 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/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE= cosmossdk.io/math v1.3.0/go.mod h1:vnRTxewy+M7BtXBNFybkuhSH4WfedVAAnERHgVFhp3k= +cosmossdk.io/schema v0.1.1 h1:I0M6pgI7R10nq+/HCQfbO6BsGBZA8sQy+duR1Y3aKcA= +cosmossdk.io/schema v0.1.1/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMbk2FiG/kXiLl8BRyzTWDw7gX/Hz7Dd5eDMs= diff --git a/simapp/app_di.go b/simapp/app_di.go index ac73c5af53fb..52c9917fd186 100644 --- a/simapp/app_di.go +++ b/simapp/app_di.go @@ -12,6 +12,7 @@ import ( "github.com/spf13/cast" clienthelpers "cosmossdk.io/client/v2/helpers" + "cosmossdk.io/core/appmodule" "cosmossdk.io/core/legacy" "cosmossdk.io/depinject" "cosmossdk.io/log" @@ -179,8 +180,10 @@ func NewSimApp( ) ) + var appModules map[string]appmodule.AppModule if err := depinject.Inject(appConfig, &appBuilder, + &appModules, &app.appCodec, &app.legacyAmino, &app.txConfig, @@ -242,9 +245,21 @@ func NewSimApp( app.App = appBuilder.Build(db, traceStore, baseAppOptions...) - // register streaming services - if err := app.RegisterStreamingServices(appOpts, app.kvStoreKeys()); err != nil { - panic(err) + if indexerOpts := appOpts.Get("indexer"); indexerOpts != nil { + // if we have indexer options in app.toml, then enable the built-in indexer framework + moduleSet := map[string]any{} + for modName, mod := range appModules { + moduleSet[modName] = mod + } + err := app.EnableIndexer(indexerOpts, app.kvStoreKeys(), moduleSet) + if err != nil { + panic(err) + } + } else { + // register legacy streaming services if we don't have the built-in indexer enabled + if err := app.RegisterStreamingServices(appOpts, app.kvStoreKeys()); err != nil { + panic(err) + } } /**** Module Options ****/ diff --git a/simapp/go.mod b/simapp/go.mod index c99893cbb88f..268c0ebd9b5f 100644 --- a/simapp/go.mod +++ b/simapp/go.mod @@ -60,6 +60,7 @@ require ( cloud.google.com/go/storage v1.42.0 // indirect cosmossdk.io/core/testing v0.0.0-00010101000000-000000000000 // indirect cosmossdk.io/errors v1.0.1 // indirect + cosmossdk.io/schema v0.1.1 // indirect filippo.io/edwards25519 v1.1.0 // indirect github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect github.com/99designs/keyring v1.2.2 // indirect diff --git a/simapp/go.sum b/simapp/go.sum index 9286d2faa635..cd13789d744b 100644 --- a/simapp/go.sum +++ b/simapp/go.sum @@ -196,6 +196,8 @@ 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/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE= cosmossdk.io/math v1.3.0/go.mod h1:vnRTxewy+M7BtXBNFybkuhSH4WfedVAAnERHgVFhp3k= +cosmossdk.io/schema v0.1.1 h1:I0M6pgI7R10nq+/HCQfbO6BsGBZA8sQy+duR1Y3aKcA= +cosmossdk.io/schema v0.1.1/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= diff --git a/simapp/v2/go.mod b/simapp/v2/go.mod index 7f8309ceab17..bac026326d52 100644 --- a/simapp/v2/go.mod +++ b/simapp/v2/go.mod @@ -62,6 +62,7 @@ require ( cloud.google.com/go/storage v1.42.0 // indirect cosmossdk.io/core/testing v0.0.0-00010101000000-000000000000 // indirect cosmossdk.io/errors v1.0.1 // indirect + cosmossdk.io/schema v0.1.1 // indirect cosmossdk.io/server/v2/appmanager v0.0.0-00010101000000-000000000000 // indirect cosmossdk.io/server/v2/stf v0.0.0-00010101000000-000000000000 // indirect cosmossdk.io/store v1.1.1-0.20240418092142-896cdf1971bc // indirect diff --git a/simapp/v2/go.sum b/simapp/v2/go.sum index bbcbb67a9614..e8a4cb4920e2 100644 --- a/simapp/v2/go.sum +++ b/simapp/v2/go.sum @@ -196,6 +196,8 @@ 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/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE= cosmossdk.io/math v1.3.0/go.mod h1:vnRTxewy+M7BtXBNFybkuhSH4WfedVAAnERHgVFhp3k= +cosmossdk.io/schema v0.1.1 h1:I0M6pgI7R10nq+/HCQfbO6BsGBZA8sQy+duR1Y3aKcA= +cosmossdk.io/schema v0.1.1/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= cosmossdk.io/x/epochs v0.0.0-20240522060652-a1ae4c3e0337 h1:GuBrfHsK3RD5vlD4DuBz3DXslR6VlnzrYmHOC3L679Q= cosmossdk.io/x/epochs v0.0.0-20240522060652-a1ae4c3e0337/go.mod h1:PhLn1pMBilyRC4GfRkoYhm+XVAYhF4adVrzut8AdpJI= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= diff --git a/tests/go.mod b/tests/go.mod index 20ae5e3ae144..e747740c0701 100644 --- a/tests/go.mod +++ b/tests/go.mod @@ -64,6 +64,7 @@ require ( cloud.google.com/go/storage v1.42.0 // indirect cosmossdk.io/client/v2 v2.0.0-20230630094428-02b760776860 // indirect cosmossdk.io/core/testing v0.0.0-00010101000000-000000000000 // indirect + cosmossdk.io/schema v0.1.1 // indirect cosmossdk.io/x/circuit v0.0.0-20230613133644-0a778132a60f // indirect cosmossdk.io/x/epochs v0.0.0-20240522060652-a1ae4c3e0337 // indirect filippo.io/edwards25519 v1.1.0 // indirect diff --git a/tests/go.sum b/tests/go.sum index 3070683b5280..d2d6c9304886 100644 --- a/tests/go.sum +++ b/tests/go.sum @@ -196,6 +196,8 @@ 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/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE= cosmossdk.io/math v1.3.0/go.mod h1:vnRTxewy+M7BtXBNFybkuhSH4WfedVAAnERHgVFhp3k= +cosmossdk.io/schema v0.1.1 h1:I0M6pgI7R10nq+/HCQfbO6BsGBZA8sQy+duR1Y3aKcA= +cosmossdk.io/schema v0.1.1/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= diff --git a/x/accounts/defaults/lockup/continuous_locking_account_test.go b/x/accounts/defaults/lockup/continuous_locking_account_test.go new file mode 100644 index 000000000000..1c5742833a81 --- /dev/null +++ b/x/accounts/defaults/lockup/continuous_locking_account_test.go @@ -0,0 +1,235 @@ +package lockup + +import ( + "context" + "testing" + "time" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/require" + + "cosmossdk.io/core/header" + "cosmossdk.io/core/store" + "cosmossdk.io/log" + "cosmossdk.io/math" + lockuptypes "cosmossdk.io/x/accounts/defaults/lockup/types" +) + +func setupContinousAccount(t *testing.T, ctx context.Context, ss store.KVStoreService) *ContinuousLockingAccount { + t.Helper() + deps := makeMockDependencies(ss) + owner := "owner" + + acc, err := NewContinuousLockingAccount(deps) + require.NoError(t, err) + _, err = acc.Init(ctx, &lockuptypes.MsgInitLockupAccount{ + Owner: owner, + EndTime: time.Now().Add(time.Minute * 2), + StartTime: time.Now(), + }) + require.NoError(t, err) + + return acc +} + +func TestContinousAccountDelegate(t *testing.T) { + ctx, ss := newMockContext(t) + sdkCtx := sdk.NewContext(nil, true, log.NewNopLogger()).WithContext(ctx).WithHeaderInfo(header.Info{ + Time: time.Now(), + }) + + acc := setupContinousAccount(t, sdkCtx, ss) + _, err := acc.Delegate(sdkCtx, &lockuptypes.MsgDelegate{ + Sender: "owner", + ValidatorAddress: "val_address", + Amount: sdk.NewCoin("test", math.NewInt(1)), + }) + require.NoError(t, err) + + delLocking, err := acc.DelegatedLocking.Get(ctx, "test") + require.NoError(t, err) + require.True(t, delLocking.Equal(math.NewInt(1))) + + startTime, err := acc.StartTime.Get(sdkCtx) + require.NoError(t, err) + + // Update context time to unlocked half of the original locking amount + sdkCtx = sdkCtx.WithHeaderInfo(header.Info{ + Time: startTime.Add(time.Minute * 1), + }) + + _, err = acc.Delegate(sdkCtx, &lockuptypes.MsgDelegate{ + Sender: "owner", + ValidatorAddress: "val_address", + Amount: sdk.NewCoin("test", math.NewInt(5)), + }) + require.NoError(t, err) + + delLocking, err = acc.DelegatedLocking.Get(ctx, "test") + require.NoError(t, err) + require.True(t, delLocking.Equal(math.NewInt(5))) + + delFree, err := acc.DelegatedFree.Get(ctx, "test") + require.NoError(t, err) + require.True(t, delFree.Equal(math.NewInt(1))) +} + +func TestContinousAccountUndelegate(t *testing.T) { + ctx, ss := newMockContext(t) + sdkCtx := sdk.NewContext(nil, true, log.NewNopLogger()).WithContext(ctx).WithHeaderInfo(header.Info{ + Time: time.Now(), + }) + + acc := setupContinousAccount(t, sdkCtx, ss) + // Delegate first + _, err := acc.Delegate(sdkCtx, &lockuptypes.MsgDelegate{ + Sender: "owner", + ValidatorAddress: "val_address", + Amount: sdk.NewCoin("test", math.NewInt(1)), + }) + require.NoError(t, err) + + delLocking, err := acc.DelegatedLocking.Get(ctx, "test") + require.NoError(t, err) + require.True(t, delLocking.Equal(math.NewInt(1))) + + // Undelegate + _, err = acc.Undelegate(sdkCtx, &lockuptypes.MsgUndelegate{ + Sender: "owner", + ValidatorAddress: "val_address", + Amount: sdk.NewCoin("test", math.NewInt(1)), + }) + require.NoError(t, err) + + delLocking, err = acc.DelegatedLocking.Get(ctx, "test") + require.NoError(t, err) + require.True(t, delLocking.Equal(math.ZeroInt())) + + startTime, err := acc.StartTime.Get(sdkCtx) + require.NoError(t, err) + + // Update context time to unlocked half of the original locking amount + sdkCtx = sdkCtx.WithHeaderInfo(header.Info{ + Time: startTime.Add(time.Minute * 1), + }) + + _, err = acc.Delegate(sdkCtx, &lockuptypes.MsgDelegate{ + Sender: "owner", + ValidatorAddress: "val_address", + Amount: sdk.NewCoin("test", math.NewInt(6)), + }) + require.NoError(t, err) + + delLocking, err = acc.DelegatedLocking.Get(ctx, "test") + require.NoError(t, err) + require.True(t, delLocking.Equal(math.NewInt(5))) + + delFree, err := acc.DelegatedFree.Get(ctx, "test") + require.NoError(t, err) + require.True(t, delFree.Equal(math.NewInt(1))) + + // Undelegate + _, err = acc.Undelegate(sdkCtx, &lockuptypes.MsgUndelegate{ + Sender: "owner", + ValidatorAddress: "val_address", + Amount: sdk.NewCoin("test", math.NewInt(4)), + }) + require.NoError(t, err) + + delLocking, err = acc.DelegatedLocking.Get(ctx, "test") + require.NoError(t, err) + require.True(t, delLocking.Equal(math.NewInt(2))) + + delFree, err = acc.DelegatedFree.Get(ctx, "test") + require.NoError(t, err) + require.True(t, delFree.Equal(math.ZeroInt())) +} + +func TestContinousAccountSendCoins(t *testing.T) { + ctx, ss := newMockContext(t) + sdkCtx := sdk.NewContext(nil, true, log.NewNopLogger()).WithContext(ctx).WithHeaderInfo(header.Info{ + Time: time.Now(), + }) + + acc := setupContinousAccount(t, sdkCtx, ss) + _, err := acc.SendCoins(sdkCtx, &lockuptypes.MsgSend{ + Sender: "owner", + ToAddress: "receiver", + Amount: sdk.NewCoins(sdk.NewCoin("test", math.NewInt(5))), + }) + require.Error(t, err) + + startTime, err := acc.StartTime.Get(sdkCtx) + require.NoError(t, err) + + // Update context time to unlocked half of the original locking amount + sdkCtx = sdkCtx.WithHeaderInfo(header.Info{ + Time: startTime.Add(time.Minute * 1), + }) + + _, err = acc.SendCoins(sdkCtx, &lockuptypes.MsgSend{ + Sender: "owner", + ToAddress: "receiver", + Amount: sdk.NewCoins(sdk.NewCoin("test", math.NewInt(5))), + }) + require.NoError(t, err) +} + +func TestContinousAccountWithdrawUnlockedCoins(t *testing.T) { + ctx, ss := newMockContext(t) + sdkCtx := sdk.NewContext(nil, true, log.NewNopLogger()).WithContext(ctx).WithHeaderInfo(header.Info{ + Time: time.Now(), + }) + + acc := setupContinousAccount(t, sdkCtx, ss) + _, err := acc.WithdrawUnlockedCoins(sdkCtx, &lockuptypes.MsgWithdraw{ + Withdrawer: "owner", + ToAddress: "receiver", + Denoms: []string{"test"}, + }) + require.Error(t, err) + + startTime, err := acc.StartTime.Get(sdkCtx) + require.NoError(t, err) + + // Update context time to unlocked half of the original locking amount + sdkCtx = sdkCtx.WithHeaderInfo(header.Info{ + Time: startTime.Add(time.Minute * 1), + }) + + _, err = acc.WithdrawUnlockedCoins(sdkCtx, &lockuptypes.MsgWithdraw{ + Withdrawer: "owner", + ToAddress: "receiver", + Denoms: []string{"test"}, + }) + require.NoError(t, err) +} + +func TestContinousAccountGetLockCoinInfo(t *testing.T) { + ctx, ss := newMockContext(t) + sdkCtx := sdk.NewContext(nil, true, log.NewNopLogger()).WithContext(ctx).WithHeaderInfo(header.Info{ + Time: time.Now(), + }) + + acc := setupContinousAccount(t, sdkCtx, ss) + + unlocked, locked, err := acc.GetLockCoinsInfo(sdkCtx, time.Now()) + require.NoError(t, err) + require.True(t, unlocked.AmountOf("test").Equal(math.ZeroInt())) + require.True(t, locked.AmountOf("test").Equal(math.NewInt(10))) + + startTime, err := acc.StartTime.Get(sdkCtx) + require.NoError(t, err) + + // unlocked half locked token + unlocked, locked, err = acc.GetLockCoinsInfo(sdkCtx, startTime.Add(time.Minute*1)) + require.NoError(t, err) + require.True(t, unlocked.AmountOf("test").Equal(math.NewInt(5))) + require.True(t, locked.AmountOf("test").Equal(math.NewInt(5))) + + // unlocked full locked token + unlocked, locked, err = acc.GetLockCoinsInfo(sdkCtx, startTime.Add(time.Minute*2)) + require.NoError(t, err) + require.True(t, unlocked.AmountOf("test").Equal(math.NewInt(10))) + require.True(t, locked.AmountOf("test").Equal(math.ZeroInt())) +} diff --git a/x/accounts/defaults/lockup/delayed_locking_account_test.go b/x/accounts/defaults/lockup/delayed_locking_account_test.go new file mode 100644 index 000000000000..2a9fa85b755c --- /dev/null +++ b/x/accounts/defaults/lockup/delayed_locking_account_test.go @@ -0,0 +1,224 @@ +package lockup + +import ( + "context" + "testing" + "time" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/require" + + "cosmossdk.io/core/header" + "cosmossdk.io/core/store" + "cosmossdk.io/log" + "cosmossdk.io/math" + lockuptypes "cosmossdk.io/x/accounts/defaults/lockup/types" +) + +func setupDelayedAccount(t *testing.T, ctx context.Context, ss store.KVStoreService) *DelayedLockingAccount { + t.Helper() + deps := makeMockDependencies(ss) + owner := "owner" + + acc, err := NewDelayedLockingAccount(deps) + require.NoError(t, err) + _, err = acc.Init(ctx, &lockuptypes.MsgInitLockupAccount{ + Owner: owner, + EndTime: time.Now().Add(time.Minute * 2), + }) + require.NoError(t, err) + + return acc +} + +func TestDelayedAccountDelegate(t *testing.T) { + ctx, ss := newMockContext(t) + sdkCtx := sdk.NewContext(nil, true, log.NewNopLogger()).WithContext(ctx).WithHeaderInfo(header.Info{ + Time: time.Now(), + }) + + acc := setupDelayedAccount(t, sdkCtx, ss) + _, err := acc.Delegate(sdkCtx, &lockuptypes.MsgDelegate{ + Sender: "owner", + ValidatorAddress: "val_address", + Amount: sdk.NewCoin("test", math.NewInt(1)), + }) + require.NoError(t, err) + + delLocking, err := acc.DelegatedLocking.Get(ctx, "test") + require.NoError(t, err) + require.True(t, delLocking.Equal(math.NewInt(1))) + + endTime, err := acc.EndTime.Get(sdkCtx) + require.NoError(t, err) + + // Update context time to unlocked all the original locking amount + sdkCtx = sdkCtx.WithHeaderInfo(header.Info{ + Time: endTime.Add(time.Second), + }) + + _, err = acc.Delegate(sdkCtx, &lockuptypes.MsgDelegate{ + Sender: "owner", + ValidatorAddress: "val_address", + Amount: sdk.NewCoin("test", math.NewInt(5)), + }) + require.NoError(t, err) + + delLocking, err = acc.DelegatedLocking.Get(ctx, "test") + require.NoError(t, err) + require.True(t, delLocking.Equal(math.NewInt(1))) + + delFree, err := acc.DelegatedFree.Get(ctx, "test") + require.NoError(t, err) + require.True(t, delFree.Equal(math.NewInt(5))) +} + +func TestDelayedAccountUndelegate(t *testing.T) { + ctx, ss := newMockContext(t) + sdkCtx := sdk.NewContext(nil, true, log.NewNopLogger()).WithContext(ctx).WithHeaderInfo(header.Info{ + Time: time.Now(), + }) + + acc := setupDelayedAccount(t, sdkCtx, ss) + // Delegate first + _, err := acc.Delegate(sdkCtx, &lockuptypes.MsgDelegate{ + Sender: "owner", + ValidatorAddress: "val_address", + Amount: sdk.NewCoin("test", math.NewInt(1)), + }) + require.NoError(t, err) + + delLocking, err := acc.DelegatedLocking.Get(ctx, "test") + require.NoError(t, err) + require.True(t, delLocking.Equal(math.NewInt(1))) + + // Undelegate + _, err = acc.Undelegate(sdkCtx, &lockuptypes.MsgUndelegate{ + Sender: "owner", + ValidatorAddress: "val_address", + Amount: sdk.NewCoin("test", math.NewInt(1)), + }) + require.NoError(t, err) + + delLocking, err = acc.DelegatedLocking.Get(ctx, "test") + require.NoError(t, err) + require.True(t, delLocking.Equal(math.ZeroInt())) + + endTime, err := acc.EndTime.Get(sdkCtx) + require.NoError(t, err) + + // Update context time to unlocked all the original locking amount + sdkCtx = sdkCtx.WithHeaderInfo(header.Info{ + Time: endTime.Add(time.Second), + }) + + _, err = acc.Delegate(sdkCtx, &lockuptypes.MsgDelegate{ + Sender: "owner", + ValidatorAddress: "val_address", + Amount: sdk.NewCoin("test", math.NewInt(6)), + }) + require.NoError(t, err) + + delLocking, err = acc.DelegatedLocking.Get(ctx, "test") + require.NoError(t, err) + require.True(t, delLocking.Equal(math.ZeroInt())) + + delFree, err := acc.DelegatedFree.Get(ctx, "test") + require.NoError(t, err) + require.True(t, delFree.Equal(math.NewInt(6))) + + // Undelegate + _, err = acc.Undelegate(sdkCtx, &lockuptypes.MsgUndelegate{ + Sender: "owner", + ValidatorAddress: "val_address", + Amount: sdk.NewCoin("test", math.NewInt(4)), + }) + require.NoError(t, err) + + delFree, err = acc.DelegatedFree.Get(ctx, "test") + require.NoError(t, err) + require.True(t, delFree.Equal(math.NewInt(2))) +} + +func TestDelayedAccountSendCoins(t *testing.T) { + ctx, ss := newMockContext(t) + sdkCtx := sdk.NewContext(nil, true, log.NewNopLogger()).WithContext(ctx).WithHeaderInfo(header.Info{ + Time: time.Now(), + }) + + acc := setupDelayedAccount(t, sdkCtx, ss) + _, err := acc.SendCoins(sdkCtx, &lockuptypes.MsgSend{ + Sender: "owner", + ToAddress: "receiver", + Amount: sdk.NewCoins(sdk.NewCoin("test", math.NewInt(5))), + }) + require.Error(t, err) + + endTime, err := acc.EndTime.Get(sdkCtx) + require.NoError(t, err) + + // Update context time to unlocked all the original locking amount + sdkCtx = sdkCtx.WithHeaderInfo(header.Info{ + Time: endTime.Add(time.Second), + }) + + _, err = acc.SendCoins(sdkCtx, &lockuptypes.MsgSend{ + Sender: "owner", + ToAddress: "receiver", + Amount: sdk.NewCoins(sdk.NewCoin("test", math.NewInt(5))), + }) + require.NoError(t, err) +} + +func TestDelayedAccountWithdrawUnlockedCoins(t *testing.T) { + ctx, ss := newMockContext(t) + sdkCtx := sdk.NewContext(nil, true, log.NewNopLogger()).WithContext(ctx).WithHeaderInfo(header.Info{ + Time: time.Now(), + }) + + acc := setupDelayedAccount(t, sdkCtx, ss) + _, err := acc.WithdrawUnlockedCoins(sdkCtx, &lockuptypes.MsgWithdraw{ + Withdrawer: "owner", + ToAddress: "receiver", + Denoms: []string{"test"}, + }) + require.Error(t, err) + + endTime, err := acc.EndTime.Get(sdkCtx) + require.NoError(t, err) + + // Update context time to unlocked all the original locking amount + sdkCtx = sdkCtx.WithHeaderInfo(header.Info{ + Time: endTime.Add(time.Second), + }) + + _, err = acc.WithdrawUnlockedCoins(sdkCtx, &lockuptypes.MsgWithdraw{ + Withdrawer: "owner", + ToAddress: "receiver", + Denoms: []string{"test"}, + }) + require.NoError(t, err) +} + +func TestDelayedAccountGetLockCoinInfo(t *testing.T) { + ctx, ss := newMockContext(t) + sdkCtx := sdk.NewContext(nil, true, log.NewNopLogger()).WithContext(ctx).WithHeaderInfo(header.Info{ + Time: time.Now(), + }) + + acc := setupDelayedAccount(t, sdkCtx, ss) + + unlocked, locked, err := acc.GetLockCoinsInfo(sdkCtx, time.Now()) + require.NoError(t, err) + require.True(t, unlocked.AmountOf("test").Equal(math.ZeroInt())) + require.True(t, locked.AmountOf("test").Equal(math.NewInt(10))) + + endTime, err := acc.EndTime.Get(sdkCtx) + require.NoError(t, err) + + // unlocked full locked token + unlocked, locked, err = acc.GetLockCoinsInfo(sdkCtx, endTime.Add(time.Second*1)) + require.NoError(t, err) + require.True(t, unlocked.AmountOf("test").Equal(math.NewInt(10))) + require.True(t, locked.AmountOf("test").Equal(math.ZeroInt())) +} diff --git a/x/accounts/defaults/lockup/go.mod b/x/accounts/defaults/lockup/go.mod index 5883327445e1..d1f198c4668e 100644 --- a/x/accounts/defaults/lockup/go.mod +++ b/x/accounts/defaults/lockup/go.mod @@ -19,6 +19,7 @@ require ( buf.build/gen/go/cometbft/cometbft/protocolbuffers/go v1.34.2-20240701160653-fedbb9acfd2f.2 // indirect cosmossdk.io/core/testing v0.0.0-00010101000000-000000000000 // indirect cosmossdk.io/depinject v1.0.0-alpha.4 // indirect + cosmossdk.io/schema v0.1.1 // indirect github.com/cometbft/cometbft/api v1.0.0-rc.1 // indirect github.com/cosmos/crypto v0.1.1 // indirect github.com/dgraph-io/badger/v4 v4.2.0 // indirect @@ -33,7 +34,7 @@ require ( buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.34.2-20240130113600-88ef6483f90f.2 // indirect cosmossdk.io/api v0.7.5 // indirect cosmossdk.io/errors v1.0.1 - cosmossdk.io/log v1.3.1 // indirect + cosmossdk.io/log v1.3.1 cosmossdk.io/math v1.3.0 cosmossdk.io/store v1.1.1-0.20240418092142-896cdf1971bc // indirect cosmossdk.io/x/auth v0.0.0-00010101000000-000000000000 // indirect @@ -81,7 +82,7 @@ require ( github.com/gogo/googleapis v1.4.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/glog v1.2.0 // indirect - github.com/golang/protobuf v1.5.4 // indirect + github.com/golang/protobuf v1.5.4 github.com/golang/snappy v0.0.4 // indirect github.com/google/btree v1.1.2 // indirect github.com/google/go-cmp v0.6.0 // indirect diff --git a/x/accounts/defaults/lockup/go.sum b/x/accounts/defaults/lockup/go.sum index b59c6def4d0a..198f6907f757 100644 --- a/x/accounts/defaults/lockup/go.sum +++ b/x/accounts/defaults/lockup/go.sum @@ -8,6 +8,8 @@ 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/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE= cosmossdk.io/math v1.3.0/go.mod h1:vnRTxewy+M7BtXBNFybkuhSH4WfedVAAnERHgVFhp3k= +cosmossdk.io/schema v0.1.1 h1:I0M6pgI7R10nq+/HCQfbO6BsGBZA8sQy+duR1Y3aKcA= +cosmossdk.io/schema v0.1.1/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= cosmossdk.io/store v1.1.1-0.20240418092142-896cdf1971bc h1:R9O9d75e0qZYUsVV0zzi+D7cNLnX2JrUOQNoIPaF0Bg= cosmossdk.io/store v1.1.1-0.20240418092142-896cdf1971bc/go.mod h1:amTTatOUV3u1PsKmNb87z6/galCxrRbz9kRdJkL0DyU= cosmossdk.io/x/tx v0.13.3 h1:Ha4mNaHmxBc6RMun9aKuqul8yHiL78EKJQ8g23Zf73g= diff --git a/x/accounts/defaults/lockup/lockup_test.go b/x/accounts/defaults/lockup/lockup_test.go index c76b16bf8820..67f3cadfbdf4 100644 --- a/x/accounts/defaults/lockup/lockup_test.go +++ b/x/accounts/defaults/lockup/lockup_test.go @@ -273,6 +273,8 @@ func TestQueryLockupAccountBaseInfo(t *testing.T) { baseLockup := setup(t, ctx, ss) - _, err := baseLockup.QueryLockupAccountBaseInfo(ctx, &lockuptypes.QueryLockupAccountInfoRequest{}) + res, err := baseLockup.QueryLockupAccountBaseInfo(ctx, &lockuptypes.QueryLockupAccountInfoRequest{}) + require.Equal(t, res.OriginalLocking.AmountOf("test"), math.NewInt(10)) + require.Equal(t, res.Owner, "owner") require.NoError(t, err) } diff --git a/x/accounts/defaults/lockup/periodic_locking_account_test.go b/x/accounts/defaults/lockup/periodic_locking_account_test.go new file mode 100644 index 000000000000..e05b033430be --- /dev/null +++ b/x/accounts/defaults/lockup/periodic_locking_account_test.go @@ -0,0 +1,274 @@ +package lockup + +import ( + "context" + "testing" + "time" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/require" + + "cosmossdk.io/core/header" + "cosmossdk.io/core/store" + "cosmossdk.io/log" + "cosmossdk.io/math" + lockuptypes "cosmossdk.io/x/accounts/defaults/lockup/types" +) + +func setupPeriodicAccount(t *testing.T, ctx context.Context, ss store.KVStoreService) *PeriodicLockingAccount { + t.Helper() + deps := makeMockDependencies(ss) + owner := "owner" + + acc, err := NewPeriodicLockingAccount(deps) + require.NoError(t, err) + _, err = acc.Init(ctx, &lockuptypes.MsgInitPeriodicLockingAccount{ + Owner: owner, + StartTime: time.Now(), + LockingPeriods: []lockuptypes.Period{ + { + Amount: sdk.NewCoins(sdk.NewCoin("test", math.NewInt(5))), + Length: time.Minute, + }, + { + Amount: sdk.NewCoins(sdk.NewCoin("test", math.NewInt(2))), + Length: time.Minute, + }, + { + Amount: sdk.NewCoins(sdk.NewCoin("test", math.NewInt(3))), + Length: time.Minute, + }, + }, + }) + require.NoError(t, err) + + return acc +} + +func TestPeriodicAccountDelegate(t *testing.T) { + ctx, ss := newMockContext(t) + sdkCtx := sdk.NewContext(nil, true, log.NewNopLogger()).WithContext(ctx).WithHeaderInfo(header.Info{ + Time: time.Now(), + }) + + acc := setupPeriodicAccount(t, sdkCtx, ss) + _, err := acc.Delegate(sdkCtx, &lockuptypes.MsgDelegate{ + Sender: "owner", + ValidatorAddress: "val_address", + Amount: sdk.NewCoin("test", math.NewInt(1)), + }) + require.NoError(t, err) + + delLocking, err := acc.DelegatedLocking.Get(ctx, "test") + require.NoError(t, err) + require.True(t, delLocking.Equal(math.NewInt(1))) + + startTime, err := acc.StartTime.Get(sdkCtx) + require.NoError(t, err) + + // Update context time to unlocked first period token + sdkCtx = sdkCtx.WithHeaderInfo(header.Info{ + Time: startTime.Add(time.Minute * 1), + }) + + _, err = acc.Delegate(sdkCtx, &lockuptypes.MsgDelegate{ + Sender: "owner", + ValidatorAddress: "val_address", + Amount: sdk.NewCoin("test", math.NewInt(5)), + }) + require.NoError(t, err) + + delLocking, err = acc.DelegatedLocking.Get(ctx, "test") + require.NoError(t, err) + require.True(t, delLocking.Equal(math.NewInt(5))) + + delFree, err := acc.DelegatedFree.Get(ctx, "test") + require.NoError(t, err) + require.True(t, delFree.Equal(math.NewInt(1))) + + // Update context time to unlocked all token + sdkCtx = sdkCtx.WithHeaderInfo(header.Info{ + Time: startTime.Add(time.Minute * 3), + }) + + _, err = acc.Delegate(sdkCtx, &lockuptypes.MsgDelegate{ + Sender: "owner", + ValidatorAddress: "val_address", + Amount: sdk.NewCoin("test", math.NewInt(4)), + }) + require.NoError(t, err) + + delLocking, err = acc.DelegatedLocking.Get(ctx, "test") + require.NoError(t, err) + require.True(t, delLocking.Equal(math.NewInt(5))) + + delFree, err = acc.DelegatedFree.Get(ctx, "test") + require.NoError(t, err) + require.True(t, delFree.Equal(math.NewInt(5))) +} + +func TestPeriodicAccountUndelegate(t *testing.T) { + ctx, ss := newMockContext(t) + sdkCtx := sdk.NewContext(nil, true, log.NewNopLogger()).WithContext(ctx).WithHeaderInfo(header.Info{ + Time: time.Now(), + }) + + acc := setupPeriodicAccount(t, sdkCtx, ss) + // Delegate first + _, err := acc.Delegate(sdkCtx, &lockuptypes.MsgDelegate{ + Sender: "owner", + ValidatorAddress: "val_address", + Amount: sdk.NewCoin("test", math.NewInt(1)), + }) + require.NoError(t, err) + + delLocking, err := acc.DelegatedLocking.Get(ctx, "test") + require.NoError(t, err) + require.True(t, delLocking.Equal(math.NewInt(1))) + + // Undelegate + _, err = acc.Undelegate(sdkCtx, &lockuptypes.MsgUndelegate{ + Sender: "owner", + ValidatorAddress: "val_address", + Amount: sdk.NewCoin("test", math.NewInt(1)), + }) + require.NoError(t, err) + + delLocking, err = acc.DelegatedLocking.Get(ctx, "test") + require.NoError(t, err) + require.True(t, delLocking.Equal(math.ZeroInt())) + + startTime, err := acc.StartTime.Get(sdkCtx) + require.NoError(t, err) + + // Update context time to unlocked first period token + sdkCtx = sdkCtx.WithHeaderInfo(header.Info{ + Time: startTime.Add(time.Minute * 1), + }) + + _, err = acc.Delegate(sdkCtx, &lockuptypes.MsgDelegate{ + Sender: "owner", + ValidatorAddress: "val_address", + Amount: sdk.NewCoin("test", math.NewInt(6)), + }) + require.NoError(t, err) + + delLocking, err = acc.DelegatedLocking.Get(ctx, "test") + require.NoError(t, err) + require.True(t, delLocking.Equal(math.NewInt(5))) + + delFree, err := acc.DelegatedFree.Get(ctx, "test") + require.NoError(t, err) + require.True(t, delFree.Equal(math.NewInt(1))) + + // Undelegate + _, err = acc.Undelegate(sdkCtx, &lockuptypes.MsgUndelegate{ + Sender: "owner", + ValidatorAddress: "val_address", + Amount: sdk.NewCoin("test", math.NewInt(4)), + }) + require.NoError(t, err) + + delLocking, err = acc.DelegatedLocking.Get(ctx, "test") + require.NoError(t, err) + require.True(t, delLocking.Equal(math.NewInt(2))) + + delFree, err = acc.DelegatedFree.Get(ctx, "test") + require.NoError(t, err) + require.True(t, delFree.Equal(math.ZeroInt())) +} + +func TestPeriodicAccountSendCoins(t *testing.T) { + ctx, ss := newMockContext(t) + sdkCtx := sdk.NewContext(nil, true, log.NewNopLogger()).WithContext(ctx).WithHeaderInfo(header.Info{ + Time: time.Now(), + }) + + acc := setupPeriodicAccount(t, sdkCtx, ss) + _, err := acc.SendCoins(sdkCtx, &lockuptypes.MsgSend{ + Sender: "owner", + ToAddress: "receiver", + Amount: sdk.NewCoins(sdk.NewCoin("test", math.NewInt(5))), + }) + require.Error(t, err) + + startTime, err := acc.StartTime.Get(sdkCtx) + require.NoError(t, err) + + // Update context time to unlocked first period token + sdkCtx = sdkCtx.WithHeaderInfo(header.Info{ + Time: startTime.Add(time.Minute * 1), + }) + + _, err = acc.SendCoins(sdkCtx, &lockuptypes.MsgSend{ + Sender: "owner", + ToAddress: "receiver", + Amount: sdk.NewCoins(sdk.NewCoin("test", math.NewInt(5))), + }) + require.NoError(t, err) +} + +func TestPeriodicAccountWithdrawUnlockedCoins(t *testing.T) { + ctx, ss := newMockContext(t) + sdkCtx := sdk.NewContext(nil, true, log.NewNopLogger()).WithContext(ctx).WithHeaderInfo(header.Info{ + Time: time.Now(), + }) + + acc := setupPeriodicAccount(t, sdkCtx, ss) + _, err := acc.WithdrawUnlockedCoins(sdkCtx, &lockuptypes.MsgWithdraw{ + Withdrawer: "owner", + ToAddress: "receiver", + Denoms: []string{"test"}, + }) + require.Error(t, err) + + startTime, err := acc.StartTime.Get(sdkCtx) + require.NoError(t, err) + + // Update context time to unlocked first period token + sdkCtx = sdkCtx.WithHeaderInfo(header.Info{ + Time: startTime.Add(time.Minute * 1), + }) + + _, err = acc.WithdrawUnlockedCoins(sdkCtx, &lockuptypes.MsgWithdraw{ + Withdrawer: "owner", + ToAddress: "receiver", + Denoms: []string{"test"}, + }) + require.NoError(t, err) +} + +func TestPeriodicAccountGetLockCoinInfo(t *testing.T) { + ctx, ss := newMockContext(t) + sdkCtx := sdk.NewContext(nil, true, log.NewNopLogger()).WithContext(ctx).WithHeaderInfo(header.Info{ + Time: time.Now(), + }) + + acc := setupPeriodicAccount(t, sdkCtx, ss) + + unlocked, locked, err := acc.GetLockCoinsInfo(sdkCtx, time.Now()) + require.NoError(t, err) + require.True(t, unlocked.AmountOf("test").Equal(math.ZeroInt())) + require.True(t, locked.AmountOf("test").Equal(math.NewInt(10))) + + startTime, err := acc.StartTime.Get(sdkCtx) + require.NoError(t, err) + + // unlocked first period locked token + unlocked, locked, err = acc.GetLockCoinsInfo(sdkCtx, startTime.Add(time.Minute*1)) + require.NoError(t, err) + require.True(t, unlocked.AmountOf("test").Equal(math.NewInt(5))) + require.True(t, locked.AmountOf("test").Equal(math.NewInt(5))) + + // unlocked second period locked token + unlocked, locked, err = acc.GetLockCoinsInfo(sdkCtx, startTime.Add(time.Minute*2)) + require.NoError(t, err) + require.True(t, unlocked.AmountOf("test").Equal(math.NewInt(7))) + require.True(t, locked.AmountOf("test").Equal(math.NewInt(3))) + + // unlocked third period locked token + unlocked, locked, err = acc.GetLockCoinsInfo(sdkCtx, startTime.Add(time.Minute*3)) + require.NoError(t, err) + require.True(t, unlocked.AmountOf("test").Equal(math.NewInt(10))) + require.True(t, locked.AmountOf("test").Equal(math.ZeroInt())) +} diff --git a/x/accounts/defaults/lockup/permanent_locking_account.go b/x/accounts/defaults/lockup/permanent_locking_account.go index 2ca615c15ba5..5e5d0dab98da 100644 --- a/x/accounts/defaults/lockup/permanent_locking_account.go +++ b/x/accounts/defaults/lockup/permanent_locking_account.go @@ -100,8 +100,9 @@ func (plva PermanentLockingAccount) RegisterInitHandler(builder *accountstd.Init func (plva PermanentLockingAccount) RegisterExecuteHandlers(builder *accountstd.ExecuteBuilder) { accountstd.RegisterExecuteHandler(builder, plva.Delegate) + accountstd.RegisterExecuteHandler(builder, plva.Undelegate) accountstd.RegisterExecuteHandler(builder, plva.SendCoins) - plva.BaseLockup.RegisterExecuteHandlers(builder) + accountstd.RegisterExecuteHandler(builder, plva.WithdrawReward) } func (plva PermanentLockingAccount) RegisterQueryHandlers(builder *accountstd.QueryBuilder) { diff --git a/x/accounts/defaults/lockup/permanent_locking_account_test.go b/x/accounts/defaults/lockup/permanent_locking_account_test.go new file mode 100644 index 000000000000..341cd3c681ca --- /dev/null +++ b/x/accounts/defaults/lockup/permanent_locking_account_test.go @@ -0,0 +1,97 @@ +package lockup + +import ( + "context" + "testing" + "time" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/require" + + "cosmossdk.io/core/header" + "cosmossdk.io/core/store" + "cosmossdk.io/log" + "cosmossdk.io/math" + lockuptypes "cosmossdk.io/x/accounts/defaults/lockup/types" +) + +func setupPermanentAccount(t *testing.T, ctx context.Context, ss store.KVStoreService) *PermanentLockingAccount { + t.Helper() + deps := makeMockDependencies(ss) + owner := "owner" + + acc, err := NewPermanentLockingAccount(deps) + require.NoError(t, err) + _, err = acc.Init(ctx, &lockuptypes.MsgInitLockupAccount{ + Owner: owner, + }) + require.NoError(t, err) + + return acc +} + +func TestPermanentAccountDelegate(t *testing.T) { + ctx, ss := newMockContext(t) + sdkCtx := sdk.NewContext(nil, true, log.NewNopLogger()).WithContext(ctx).WithHeaderInfo(header.Info{ + Time: time.Now(), + }) + + acc := setupPermanentAccount(t, sdkCtx, ss) + _, err := acc.Delegate(sdkCtx, &lockuptypes.MsgDelegate{ + Sender: "owner", + ValidatorAddress: "val_address", + Amount: sdk.NewCoin("test", math.NewInt(1)), + }) + require.NoError(t, err) + + delLocking, err := acc.DelegatedLocking.Get(ctx, "test") + require.NoError(t, err) + require.True(t, delLocking.Equal(math.NewInt(1))) +} + +func TestPermanentAccountUndelegate(t *testing.T) { + ctx, ss := newMockContext(t) + sdkCtx := sdk.NewContext(nil, true, log.NewNopLogger()).WithContext(ctx).WithHeaderInfo(header.Info{ + Time: time.Now(), + }) + + acc := setupPermanentAccount(t, sdkCtx, ss) + // Delegate first + _, err := acc.Delegate(sdkCtx, &lockuptypes.MsgDelegate{ + Sender: "owner", + ValidatorAddress: "val_address", + Amount: sdk.NewCoin("test", math.NewInt(1)), + }) + require.NoError(t, err) + + delLocking, err := acc.DelegatedLocking.Get(ctx, "test") + require.NoError(t, err) + require.True(t, delLocking.Equal(math.NewInt(1))) + + // Undelegate + _, err = acc.Undelegate(sdkCtx, &lockuptypes.MsgUndelegate{ + Sender: "owner", + ValidatorAddress: "val_address", + Amount: sdk.NewCoin("test", math.NewInt(1)), + }) + require.NoError(t, err) + + delLocking, err = acc.DelegatedLocking.Get(ctx, "test") + require.NoError(t, err) + require.True(t, delLocking.Equal(math.ZeroInt())) +} + +func TestPermanentAccountSendCoins(t *testing.T) { + ctx, ss := newMockContext(t) + sdkCtx := sdk.NewContext(nil, true, log.NewNopLogger()).WithContext(ctx).WithHeaderInfo(header.Info{ + Time: time.Now(), + }) + + acc := setupPermanentAccount(t, sdkCtx, ss) + _, err := acc.SendCoins(sdkCtx, &lockuptypes.MsgSend{ + Sender: "owner", + ToAddress: "receiver", + Amount: sdk.NewCoins(sdk.NewCoin("test", math.NewInt(5))), + }) + require.Error(t, err) +} diff --git a/x/accounts/defaults/lockup/utils_test.go b/x/accounts/defaults/lockup/utils_test.go index 6dd435512ebf..56cd3316edea 100644 --- a/x/accounts/defaults/lockup/utils_test.go +++ b/x/accounts/defaults/lockup/utils_test.go @@ -2,19 +2,25 @@ package lockup import ( "context" + "fmt" "testing" gogoproto "github.com/cosmos/gogoproto/proto" + "github.com/golang/protobuf/proto" // nolint: staticcheck // needed because gogoproto.Merge does not work consistently. See NOTE: comments. "github.com/stretchr/testify/require" "google.golang.org/protobuf/runtime/protoiface" "cosmossdk.io/collections" + "cosmossdk.io/core/appmodule/v2" + "cosmossdk.io/core/header" "cosmossdk.io/core/store" "cosmossdk.io/math" "cosmossdk.io/x/accounts/accountstd" banktypes "cosmossdk.io/x/bank/types" + distrtypes "cosmossdk.io/x/distribution/types" stakingtypes "cosmossdk.io/x/staking/types" + "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" ) @@ -23,7 +29,11 @@ type ProtoMsg = protoiface.MessageV1 var TestFunds = sdk.NewCoins(sdk.NewCoin("test", math.NewInt(10))) // mock statecodec -type mockStateCodec struct{} +type mockStateCodec struct { + codec.Codec +} + +var _ codec.Codec = mockStateCodec{} func (c mockStateCodec) Marshal(m gogoproto.Message) ([]byte, error) { // Size() check can catch the typed nil value. @@ -53,13 +63,32 @@ type addressCodec struct{} func (a addressCodec) StringToBytes(text string) ([]byte, error) { return []byte(text), nil } func (a addressCodec) BytesToString(bz []byte) (string, error) { return string(bz), nil } +// mock header service +type headerService struct{} + +func (h headerService) HeaderInfo(ctx context.Context) header.Info { + return sdk.UnwrapSDKContext(ctx).HeaderInfo() +} + func newMockContext(t *testing.T) (context.Context, store.KVStoreService) { t.Helper() return accountstd.NewMockContext( 0, []byte("lockup_account"), []byte("sender"), TestFunds, func(ctx context.Context, sender []byte, msg, msgResp ProtoMsg) error { return nil }, func(ctx context.Context, sender []byte, msg ProtoMsg) (ProtoMsg, error) { - return nil, nil + typeUrl := sdk.MsgTypeURL(msg) + switch typeUrl { + case "/cosmos.staking.v1beta1.MsgDelegate": + return &stakingtypes.MsgDelegateResponse{}, nil + case "/cosmos.staking.v1beta1.MsgUndelegate": + return &stakingtypes.MsgUndelegate{}, nil + case "/cosmos.distribution.v1beta1.MsgWithdrawDelegatorReward": + return &distrtypes.MsgWithdrawDelegatorRewardResponse{}, nil + case "/cosmos.bank.v1beta1.MsgSend": + return &banktypes.MsgSendResponse{}, nil + default: + return nil, fmt.Errorf("unrecognized request type") + } }, func(ctx context.Context, req, resp ProtoMsg) error { _, ok := req.(*banktypes.QueryBalanceRequest) if !ok { @@ -70,14 +99,16 @@ func newMockContext(t *testing.T) (context.Context, store.KVStoreService) { BondDenom: "test", }, }) - return nil + } else { + // NOTE: using gogoproto.Merge will fail for some reason unknown to me, but + // using proto.Merge with gogo messages seems to work fine. + proto.Merge(resp.(gogoproto.Message), &banktypes.QueryBalanceResponse{ + Balance: &(sdk.Coin{ + Denom: "test", + Amount: TestFunds.AmountOf("test"), + }), + }) } - gogoproto.Merge(resp.(gogoproto.Message), &banktypes.QueryBalanceResponse{ - Balance: &sdk.Coin{ - Denom: "test", - Amount: math.NewInt(5), - }, - }) return nil }, @@ -91,5 +122,8 @@ func makeMockDependencies(storeservice store.KVStoreService) accountstd.Dependen SchemaBuilder: sb, AddressCodec: addressCodec{}, LegacyStateCodec: mockStateCodec{}, + Environment: appmodule.Environment{ + HeaderService: headerService{}, + }, } } diff --git a/x/accounts/go.mod b/x/accounts/go.mod index b2ca8c8b5592..f9917e9821ba 100644 --- a/x/accounts/go.mod +++ b/x/accounts/go.mod @@ -21,7 +21,10 @@ require ( require github.com/golang/mock v1.6.0 // indirect -require github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect +require ( + cosmossdk.io/schema v0.1.1 // indirect + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect +) require ( buf.build/gen/go/cometbft/cometbft/protocolbuffers/go v1.34.2-20240701160653-fedbb9acfd2f.2 // indirect diff --git a/x/accounts/go.sum b/x/accounts/go.sum index 25290d157bef..55640e3682fe 100644 --- a/x/accounts/go.sum +++ b/x/accounts/go.sum @@ -8,6 +8,8 @@ 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/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE= cosmossdk.io/math v1.3.0/go.mod h1:vnRTxewy+M7BtXBNFybkuhSH4WfedVAAnERHgVFhp3k= +cosmossdk.io/schema v0.1.1 h1:I0M6pgI7R10nq+/HCQfbO6BsGBZA8sQy+duR1Y3aKcA= +cosmossdk.io/schema v0.1.1/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= cosmossdk.io/store v1.1.1-0.20240418092142-896cdf1971bc h1:R9O9d75e0qZYUsVV0zzi+D7cNLnX2JrUOQNoIPaF0Bg= cosmossdk.io/store v1.1.1-0.20240418092142-896cdf1971bc/go.mod h1:amTTatOUV3u1PsKmNb87z6/galCxrRbz9kRdJkL0DyU= cosmossdk.io/x/accounts/defaults/lockup v0.0.0-20240417181816-5e7aae0db1f5 h1:eb0kcGyaYHSS0do7+MIWg7UKlskSH01biRNENbm/zDA= diff --git a/x/auth/go.mod b/x/auth/go.mod index 5546bd71de46..838183724117 100644 --- a/x/auth/go.mod +++ b/x/auth/go.mod @@ -38,6 +38,7 @@ require ( buf.build/gen/go/cometbft/cometbft/protocolbuffers/go v1.34.2-20240701160653-fedbb9acfd2f.2 // indirect buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.34.2-20240130113600-88ef6483f90f.2 // indirect cosmossdk.io/log v1.3.1 // indirect + cosmossdk.io/schema v0.1.1 // indirect cosmossdk.io/x/bank v0.0.0-20240226161501-23359a0b6d91 // indirect cosmossdk.io/x/staking v0.0.0-00010101000000-000000000000 // indirect filippo.io/edwards25519 v1.1.0 // indirect diff --git a/x/auth/go.sum b/x/auth/go.sum index 6a55b551b818..1ce5e4221f18 100644 --- a/x/auth/go.sum +++ b/x/auth/go.sum @@ -8,6 +8,8 @@ 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/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE= cosmossdk.io/math v1.3.0/go.mod h1:vnRTxewy+M7BtXBNFybkuhSH4WfedVAAnERHgVFhp3k= +cosmossdk.io/schema v0.1.1 h1:I0M6pgI7R10nq+/HCQfbO6BsGBZA8sQy+duR1Y3aKcA= +cosmossdk.io/schema v0.1.1/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= cosmossdk.io/store v1.1.1-0.20240418092142-896cdf1971bc h1:R9O9d75e0qZYUsVV0zzi+D7cNLnX2JrUOQNoIPaF0Bg= cosmossdk.io/store v1.1.1-0.20240418092142-896cdf1971bc/go.mod h1:amTTatOUV3u1PsKmNb87z6/galCxrRbz9kRdJkL0DyU= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= diff --git a/x/authz/go.mod b/x/authz/go.mod index f76a67cac84b..8507c160db61 100644 --- a/x/authz/go.mod +++ b/x/authz/go.mod @@ -167,7 +167,10 @@ require ( sigs.k8s.io/yaml v1.4.0 // indirect ) -require github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect +require ( + cosmossdk.io/schema v0.1.1 // indirect + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect +) replace github.com/cosmos/cosmos-sdk => ../../. diff --git a/x/authz/go.sum b/x/authz/go.sum index 6a55b551b818..1ce5e4221f18 100644 --- a/x/authz/go.sum +++ b/x/authz/go.sum @@ -8,6 +8,8 @@ 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/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE= cosmossdk.io/math v1.3.0/go.mod h1:vnRTxewy+M7BtXBNFybkuhSH4WfedVAAnERHgVFhp3k= +cosmossdk.io/schema v0.1.1 h1:I0M6pgI7R10nq+/HCQfbO6BsGBZA8sQy+duR1Y3aKcA= +cosmossdk.io/schema v0.1.1/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= cosmossdk.io/store v1.1.1-0.20240418092142-896cdf1971bc h1:R9O9d75e0qZYUsVV0zzi+D7cNLnX2JrUOQNoIPaF0Bg= cosmossdk.io/store v1.1.1-0.20240418092142-896cdf1971bc/go.mod h1:amTTatOUV3u1PsKmNb87z6/galCxrRbz9kRdJkL0DyU= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= diff --git a/x/bank/go.mod b/x/bank/go.mod index b6a0be5f191c..48ecafe138d7 100644 --- a/x/bank/go.mod +++ b/x/bank/go.mod @@ -166,7 +166,10 @@ require ( sigs.k8s.io/yaml v1.4.0 // indirect ) -require github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect +require ( + cosmossdk.io/schema v0.1.1 // indirect + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect +) replace github.com/cosmos/cosmos-sdk => ../../. diff --git a/x/bank/go.sum b/x/bank/go.sum index 6a55b551b818..1ce5e4221f18 100644 --- a/x/bank/go.sum +++ b/x/bank/go.sum @@ -8,6 +8,8 @@ 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/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE= cosmossdk.io/math v1.3.0/go.mod h1:vnRTxewy+M7BtXBNFybkuhSH4WfedVAAnERHgVFhp3k= +cosmossdk.io/schema v0.1.1 h1:I0M6pgI7R10nq+/HCQfbO6BsGBZA8sQy+duR1Y3aKcA= +cosmossdk.io/schema v0.1.1/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= cosmossdk.io/store v1.1.1-0.20240418092142-896cdf1971bc h1:R9O9d75e0qZYUsVV0zzi+D7cNLnX2JrUOQNoIPaF0Bg= cosmossdk.io/store v1.1.1-0.20240418092142-896cdf1971bc/go.mod h1:amTTatOUV3u1PsKmNb87z6/galCxrRbz9kRdJkL0DyU= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= diff --git a/x/circuit/go.mod b/x/circuit/go.mod index 18714f7e8ac4..b3e6dbd2df1f 100644 --- a/x/circuit/go.mod +++ b/x/circuit/go.mod @@ -24,6 +24,7 @@ require ( buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.34.2-20240130113600-88ef6483f90f.2 // indirect cosmossdk.io/log v1.3.1 // indirect cosmossdk.io/math v1.3.0 // indirect + cosmossdk.io/schema v0.1.1 // indirect cosmossdk.io/x/bank v0.0.0-20240226161501-23359a0b6d91 // indirect cosmossdk.io/x/consensus v0.0.0-00010101000000-000000000000 // indirect cosmossdk.io/x/staking v0.0.0-00010101000000-000000000000 // indirect diff --git a/x/circuit/go.sum b/x/circuit/go.sum index 9cea23da5e95..5a0fa777d9c1 100644 --- a/x/circuit/go.sum +++ b/x/circuit/go.sum @@ -10,6 +10,8 @@ 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/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE= cosmossdk.io/math v1.3.0/go.mod h1:vnRTxewy+M7BtXBNFybkuhSH4WfedVAAnERHgVFhp3k= +cosmossdk.io/schema v0.1.1 h1:I0M6pgI7R10nq+/HCQfbO6BsGBZA8sQy+duR1Y3aKcA= +cosmossdk.io/schema v0.1.1/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= cosmossdk.io/store v1.1.1-0.20240418092142-896cdf1971bc h1:R9O9d75e0qZYUsVV0zzi+D7cNLnX2JrUOQNoIPaF0Bg= cosmossdk.io/store v1.1.1-0.20240418092142-896cdf1971bc/go.mod h1:amTTatOUV3u1PsKmNb87z6/galCxrRbz9kRdJkL0DyU= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= diff --git a/x/consensus/go.mod b/x/consensus/go.mod index 6adbd307ae80..0f4e57e68761 100644 --- a/x/consensus/go.mod +++ b/x/consensus/go.mod @@ -26,6 +26,7 @@ require ( cosmossdk.io/errors v1.0.1 // indirect cosmossdk.io/log v1.3.1 // indirect cosmossdk.io/math v1.3.0 // indirect + cosmossdk.io/schema v0.1.1 // indirect cosmossdk.io/x/auth v0.0.0-00010101000000-000000000000 // indirect cosmossdk.io/x/bank v0.0.0-20240226161501-23359a0b6d91 // indirect cosmossdk.io/x/staking v0.0.0-00010101000000-000000000000 // indirect diff --git a/x/consensus/go.sum b/x/consensus/go.sum index e173e0113051..8db3d705f97b 100644 --- a/x/consensus/go.sum +++ b/x/consensus/go.sum @@ -10,6 +10,8 @@ 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/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE= cosmossdk.io/math v1.3.0/go.mod h1:vnRTxewy+M7BtXBNFybkuhSH4WfedVAAnERHgVFhp3k= +cosmossdk.io/schema v0.1.1 h1:I0M6pgI7R10nq+/HCQfbO6BsGBZA8sQy+duR1Y3aKcA= +cosmossdk.io/schema v0.1.1/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= cosmossdk.io/store v1.1.1-0.20240418092142-896cdf1971bc h1:R9O9d75e0qZYUsVV0zzi+D7cNLnX2JrUOQNoIPaF0Bg= cosmossdk.io/store v1.1.1-0.20240418092142-896cdf1971bc/go.mod h1:amTTatOUV3u1PsKmNb87z6/galCxrRbz9kRdJkL0DyU= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= diff --git a/x/distribution/go.mod b/x/distribution/go.mod index 8a0e9df7c681..2177e46d986b 100644 --- a/x/distribution/go.mod +++ b/x/distribution/go.mod @@ -30,6 +30,7 @@ require ( ) require ( + cosmossdk.io/schema v0.1.1 // indirect github.com/cockroachdb/errors v1.11.1 // indirect github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect diff --git a/x/distribution/go.sum b/x/distribution/go.sum index 14f26e089dd9..b84a6c810c82 100644 --- a/x/distribution/go.sum +++ b/x/distribution/go.sum @@ -8,6 +8,8 @@ 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/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE= cosmossdk.io/math v1.3.0/go.mod h1:vnRTxewy+M7BtXBNFybkuhSH4WfedVAAnERHgVFhp3k= +cosmossdk.io/schema v0.1.1 h1:I0M6pgI7R10nq+/HCQfbO6BsGBZA8sQy+duR1Y3aKcA= +cosmossdk.io/schema v0.1.1/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= cosmossdk.io/store v1.1.1-0.20240418092142-896cdf1971bc h1:R9O9d75e0qZYUsVV0zzi+D7cNLnX2JrUOQNoIPaF0Bg= cosmossdk.io/store v1.1.1-0.20240418092142-896cdf1971bc/go.mod h1:amTTatOUV3u1PsKmNb87z6/galCxrRbz9kRdJkL0DyU= cosmossdk.io/x/protocolpool v0.0.0-20230925135524-a1bc045b3190 h1:XQJj9Dv9Gtze0l2TF79BU5lkP6MkUveTUuKICmxoz+o= diff --git a/x/epochs/go.mod b/x/epochs/go.mod index 7aaf3ebad844..5b1458e79b84 100644 --- a/x/epochs/go.mod +++ b/x/epochs/go.mod @@ -165,6 +165,7 @@ require ( require ( cosmossdk.io/log v1.3.1 // indirect + cosmossdk.io/schema v0.1.1 // indirect cosmossdk.io/x/consensus v0.0.0-00010101000000-000000000000 // indirect github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect diff --git a/x/epochs/go.sum b/x/epochs/go.sum index e173e0113051..8db3d705f97b 100644 --- a/x/epochs/go.sum +++ b/x/epochs/go.sum @@ -10,6 +10,8 @@ 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/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE= cosmossdk.io/math v1.3.0/go.mod h1:vnRTxewy+M7BtXBNFybkuhSH4WfedVAAnERHgVFhp3k= +cosmossdk.io/schema v0.1.1 h1:I0M6pgI7R10nq+/HCQfbO6BsGBZA8sQy+duR1Y3aKcA= +cosmossdk.io/schema v0.1.1/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= cosmossdk.io/store v1.1.1-0.20240418092142-896cdf1971bc h1:R9O9d75e0qZYUsVV0zzi+D7cNLnX2JrUOQNoIPaF0Bg= cosmossdk.io/store v1.1.1-0.20240418092142-896cdf1971bc/go.mod h1:amTTatOUV3u1PsKmNb87z6/galCxrRbz9kRdJkL0DyU= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= diff --git a/x/evidence/go.mod b/x/evidence/go.mod index 2e45731e33c4..814c81901cdf 100644 --- a/x/evidence/go.mod +++ b/x/evidence/go.mod @@ -28,6 +28,7 @@ require ( buf.build/gen/go/cometbft/cometbft/protocolbuffers/go v1.34.2-20240701160653-fedbb9acfd2f.2 // indirect buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.34.2-20240130113600-88ef6483f90f.2 // indirect cosmossdk.io/log v1.3.1 // indirect + cosmossdk.io/schema v0.1.1 // indirect cosmossdk.io/x/auth v0.0.0-00010101000000-000000000000 // indirect cosmossdk.io/x/bank v0.0.0-20240226161501-23359a0b6d91 // indirect cosmossdk.io/x/staking v0.0.0-00010101000000-000000000000 // indirect diff --git a/x/evidence/go.sum b/x/evidence/go.sum index 9cea23da5e95..5a0fa777d9c1 100644 --- a/x/evidence/go.sum +++ b/x/evidence/go.sum @@ -10,6 +10,8 @@ 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/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE= cosmossdk.io/math v1.3.0/go.mod h1:vnRTxewy+M7BtXBNFybkuhSH4WfedVAAnERHgVFhp3k= +cosmossdk.io/schema v0.1.1 h1:I0M6pgI7R10nq+/HCQfbO6BsGBZA8sQy+duR1Y3aKcA= +cosmossdk.io/schema v0.1.1/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= cosmossdk.io/store v1.1.1-0.20240418092142-896cdf1971bc h1:R9O9d75e0qZYUsVV0zzi+D7cNLnX2JrUOQNoIPaF0Bg= cosmossdk.io/store v1.1.1-0.20240418092142-896cdf1971bc/go.mod h1:amTTatOUV3u1PsKmNb87z6/galCxrRbz9kRdJkL0DyU= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= diff --git a/x/feegrant/go.mod b/x/feegrant/go.mod index 0082f43338db..c6e598a63dca 100644 --- a/x/feegrant/go.mod +++ b/x/feegrant/go.mod @@ -171,7 +171,10 @@ require ( sigs.k8s.io/yaml v1.4.0 // indirect ) -require github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect +require ( + cosmossdk.io/schema v0.1.1 // indirect + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect +) replace github.com/cosmos/cosmos-sdk => ../../. diff --git a/x/feegrant/go.sum b/x/feegrant/go.sum index 59a4832bba4a..93c41c66141d 100644 --- a/x/feegrant/go.sum +++ b/x/feegrant/go.sum @@ -8,6 +8,8 @@ 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/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE= cosmossdk.io/math v1.3.0/go.mod h1:vnRTxewy+M7BtXBNFybkuhSH4WfedVAAnERHgVFhp3k= +cosmossdk.io/schema v0.1.1 h1:I0M6pgI7R10nq+/HCQfbO6BsGBZA8sQy+duR1Y3aKcA= +cosmossdk.io/schema v0.1.1/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= cosmossdk.io/store v1.1.1-0.20240418092142-896cdf1971bc h1:R9O9d75e0qZYUsVV0zzi+D7cNLnX2JrUOQNoIPaF0Bg= cosmossdk.io/store v1.1.1-0.20240418092142-896cdf1971bc/go.mod h1:amTTatOUV3u1PsKmNb87z6/galCxrRbz9kRdJkL0DyU= cosmossdk.io/x/protocolpool v0.0.0-20230925135524-a1bc045b3190 h1:XQJj9Dv9Gtze0l2TF79BU5lkP6MkUveTUuKICmxoz+o= diff --git a/x/gov/go.mod b/x/gov/go.mod index 92efbf8c3c80..59d1fc34ff8c 100644 --- a/x/gov/go.mod +++ b/x/gov/go.mod @@ -170,7 +170,10 @@ require ( sigs.k8s.io/yaml v1.4.0 // indirect ) -require github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect +require ( + cosmossdk.io/schema v0.1.1 // indirect + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect +) replace github.com/cosmos/cosmos-sdk => ../../. diff --git a/x/gov/go.sum b/x/gov/go.sum index 6cf5f238d3d2..7cc59dc9ba10 100644 --- a/x/gov/go.sum +++ b/x/gov/go.sum @@ -8,6 +8,8 @@ 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/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE= cosmossdk.io/math v1.3.0/go.mod h1:vnRTxewy+M7BtXBNFybkuhSH4WfedVAAnERHgVFhp3k= +cosmossdk.io/schema v0.1.1 h1:I0M6pgI7R10nq+/HCQfbO6BsGBZA8sQy+duR1Y3aKcA= +cosmossdk.io/schema v0.1.1/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= cosmossdk.io/store v1.1.1-0.20240418092142-896cdf1971bc h1:R9O9d75e0qZYUsVV0zzi+D7cNLnX2JrUOQNoIPaF0Bg= cosmossdk.io/store v1.1.1-0.20240418092142-896cdf1971bc/go.mod h1:amTTatOUV3u1PsKmNb87z6/galCxrRbz9kRdJkL0DyU= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= diff --git a/x/group/go.mod b/x/group/go.mod index 37eccf21f606..7e977108eaf2 100644 --- a/x/group/go.mod +++ b/x/group/go.mod @@ -43,6 +43,7 @@ require ( buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.34.2-20240130113600-88ef6483f90f.2 // indirect cosmossdk.io/collections v0.4.0 // indirect cosmossdk.io/core/testing v0.0.0-00010101000000-000000000000 // indirect + cosmossdk.io/schema v0.1.1 // indirect cosmossdk.io/x/accounts/defaults/lockup v0.0.0-20240417181816-5e7aae0db1f5 // indirect cosmossdk.io/x/epochs v0.0.0-20240522060652-a1ae4c3e0337 // indirect cosmossdk.io/x/tx v0.13.3 // indirect diff --git a/x/group/go.sum b/x/group/go.sum index 9887054997e1..77ef188f41ac 100644 --- a/x/group/go.sum +++ b/x/group/go.sum @@ -8,6 +8,8 @@ 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/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE= cosmossdk.io/math v1.3.0/go.mod h1:vnRTxewy+M7BtXBNFybkuhSH4WfedVAAnERHgVFhp3k= +cosmossdk.io/schema v0.1.1 h1:I0M6pgI7R10nq+/HCQfbO6BsGBZA8sQy+duR1Y3aKcA= +cosmossdk.io/schema v0.1.1/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= cosmossdk.io/store v1.1.1-0.20240418092142-896cdf1971bc h1:R9O9d75e0qZYUsVV0zzi+D7cNLnX2JrUOQNoIPaF0Bg= cosmossdk.io/store v1.1.1-0.20240418092142-896cdf1971bc/go.mod h1:amTTatOUV3u1PsKmNb87z6/galCxrRbz9kRdJkL0DyU= cosmossdk.io/x/accounts/defaults/lockup v0.0.0-20240417181816-5e7aae0db1f5 h1:eb0kcGyaYHSS0do7+MIWg7UKlskSH01biRNENbm/zDA= diff --git a/x/mint/go.mod b/x/mint/go.mod index f286acecd279..906e7d7c0ed9 100644 --- a/x/mint/go.mod +++ b/x/mint/go.mod @@ -159,6 +159,7 @@ require ( require ( buf.build/gen/go/cometbft/cometbft/protocolbuffers/go v1.34.2-20240701160653-fedbb9acfd2f.2 // indirect + cosmossdk.io/schema v0.1.1 // indirect cosmossdk.io/x/consensus v0.0.0-00010101000000-000000000000 // indirect github.com/cometbft/cometbft/api v1.0.0-rc.1 // indirect github.com/cosmos/crypto v0.1.1 // indirect diff --git a/x/mint/go.sum b/x/mint/go.sum index 4ec22d5ddd4e..4791a38220ef 100644 --- a/x/mint/go.sum +++ b/x/mint/go.sum @@ -10,6 +10,8 @@ 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/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE= cosmossdk.io/math v1.3.0/go.mod h1:vnRTxewy+M7BtXBNFybkuhSH4WfedVAAnERHgVFhp3k= +cosmossdk.io/schema v0.1.1 h1:I0M6pgI7R10nq+/HCQfbO6BsGBZA8sQy+duR1Y3aKcA= +cosmossdk.io/schema v0.1.1/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= cosmossdk.io/store v1.1.1-0.20240418092142-896cdf1971bc h1:R9O9d75e0qZYUsVV0zzi+D7cNLnX2JrUOQNoIPaF0Bg= cosmossdk.io/store v1.1.1-0.20240418092142-896cdf1971bc/go.mod h1:amTTatOUV3u1PsKmNb87z6/galCxrRbz9kRdJkL0DyU= cosmossdk.io/x/epochs v0.0.0-20240522060652-a1ae4c3e0337 h1:GuBrfHsK3RD5vlD4DuBz3DXslR6VlnzrYmHOC3L679Q= diff --git a/x/nft/go.mod b/x/nft/go.mod index 10037c6b0749..e920ddadcdf0 100644 --- a/x/nft/go.mod +++ b/x/nft/go.mod @@ -25,6 +25,7 @@ require ( buf.build/gen/go/cometbft/cometbft/protocolbuffers/go v1.34.2-20240701160653-fedbb9acfd2f.2 // indirect buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.34.2-20240130113600-88ef6483f90f.2 // indirect cosmossdk.io/collections v0.4.0 // indirect + cosmossdk.io/schema v0.1.1 // indirect cosmossdk.io/x/auth v0.0.0-00010101000000-000000000000 // indirect cosmossdk.io/x/bank v0.0.0-20240226161501-23359a0b6d91 // indirect cosmossdk.io/x/consensus v0.0.0-00010101000000-000000000000 // indirect diff --git a/x/nft/go.sum b/x/nft/go.sum index 9cea23da5e95..5a0fa777d9c1 100644 --- a/x/nft/go.sum +++ b/x/nft/go.sum @@ -10,6 +10,8 @@ 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/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE= cosmossdk.io/math v1.3.0/go.mod h1:vnRTxewy+M7BtXBNFybkuhSH4WfedVAAnERHgVFhp3k= +cosmossdk.io/schema v0.1.1 h1:I0M6pgI7R10nq+/HCQfbO6BsGBZA8sQy+duR1Y3aKcA= +cosmossdk.io/schema v0.1.1/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= cosmossdk.io/store v1.1.1-0.20240418092142-896cdf1971bc h1:R9O9d75e0qZYUsVV0zzi+D7cNLnX2JrUOQNoIPaF0Bg= cosmossdk.io/store v1.1.1-0.20240418092142-896cdf1971bc/go.mod h1:amTTatOUV3u1PsKmNb87z6/galCxrRbz9kRdJkL0DyU= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= diff --git a/x/params/go.mod b/x/params/go.mod index fc95311d927b..cc265a0e6172 100644 --- a/x/params/go.mod +++ b/x/params/go.mod @@ -29,6 +29,7 @@ require ( buf.build/gen/go/cometbft/cometbft/protocolbuffers/go v1.34.2-20240701160653-fedbb9acfd2f.2 // indirect buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.34.2-20240130113600-88ef6483f90f.2 // indirect cosmossdk.io/collections v0.4.0 // indirect + cosmossdk.io/schema v0.1.1 // indirect cosmossdk.io/x/auth v0.0.0-00010101000000-000000000000 // indirect cosmossdk.io/x/bank v0.0.0-20240226161501-23359a0b6d91 // indirect cosmossdk.io/x/consensus v0.0.0-00010101000000-000000000000 // indirect diff --git a/x/params/go.sum b/x/params/go.sum index 9cea23da5e95..5a0fa777d9c1 100644 --- a/x/params/go.sum +++ b/x/params/go.sum @@ -10,6 +10,8 @@ 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/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE= cosmossdk.io/math v1.3.0/go.mod h1:vnRTxewy+M7BtXBNFybkuhSH4WfedVAAnERHgVFhp3k= +cosmossdk.io/schema v0.1.1 h1:I0M6pgI7R10nq+/HCQfbO6BsGBZA8sQy+duR1Y3aKcA= +cosmossdk.io/schema v0.1.1/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= cosmossdk.io/store v1.1.1-0.20240418092142-896cdf1971bc h1:R9O9d75e0qZYUsVV0zzi+D7cNLnX2JrUOQNoIPaF0Bg= cosmossdk.io/store v1.1.1-0.20240418092142-896cdf1971bc/go.mod h1:amTTatOUV3u1PsKmNb87z6/galCxrRbz9kRdJkL0DyU= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= diff --git a/x/protocolpool/go.mod b/x/protocolpool/go.mod index ec89c50376d1..feb5b5b5942a 100644 --- a/x/protocolpool/go.mod +++ b/x/protocolpool/go.mod @@ -28,6 +28,7 @@ require ( require ( buf.build/gen/go/cometbft/cometbft/protocolbuffers/go v1.34.2-20240701160653-fedbb9acfd2f.2 // indirect buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.34.2-20240130113600-88ef6483f90f.2 // indirect + cosmossdk.io/schema v0.1.1 // indirect cosmossdk.io/x/bank v0.0.0-20240226161501-23359a0b6d91 // indirect cosmossdk.io/x/consensus v0.0.0-00010101000000-000000000000 // indirect cosmossdk.io/x/staking v0.0.0-00010101000000-000000000000 // indirect diff --git a/x/protocolpool/go.sum b/x/protocolpool/go.sum index 9cea23da5e95..5a0fa777d9c1 100644 --- a/x/protocolpool/go.sum +++ b/x/protocolpool/go.sum @@ -10,6 +10,8 @@ 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/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE= cosmossdk.io/math v1.3.0/go.mod h1:vnRTxewy+M7BtXBNFybkuhSH4WfedVAAnERHgVFhp3k= +cosmossdk.io/schema v0.1.1 h1:I0M6pgI7R10nq+/HCQfbO6BsGBZA8sQy+duR1Y3aKcA= +cosmossdk.io/schema v0.1.1/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= cosmossdk.io/store v1.1.1-0.20240418092142-896cdf1971bc h1:R9O9d75e0qZYUsVV0zzi+D7cNLnX2JrUOQNoIPaF0Bg= cosmossdk.io/store v1.1.1-0.20240418092142-896cdf1971bc/go.mod h1:amTTatOUV3u1PsKmNb87z6/galCxrRbz9kRdJkL0DyU= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= diff --git a/x/slashing/go.mod b/x/slashing/go.mod index 1d9ebe756497..a6ab6758d032 100644 --- a/x/slashing/go.mod +++ b/x/slashing/go.mod @@ -30,6 +30,7 @@ require ( buf.build/gen/go/cometbft/cometbft/protocolbuffers/go v1.34.2-20240701160653-fedbb9acfd2f.2 // indirect buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.34.2-20240130113600-88ef6483f90f.2 // indirect cosmossdk.io/log v1.3.1 // indirect + cosmossdk.io/schema v0.1.1 // indirect cosmossdk.io/x/bank v0.0.0-20240226161501-23359a0b6d91 // indirect cosmossdk.io/x/consensus v0.0.0-00010101000000-000000000000 // indirect cosmossdk.io/x/tx v0.13.3 // indirect diff --git a/x/slashing/go.sum b/x/slashing/go.sum index 4bca15775b26..16281a3789d1 100644 --- a/x/slashing/go.sum +++ b/x/slashing/go.sum @@ -10,6 +10,8 @@ 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/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE= cosmossdk.io/math v1.3.0/go.mod h1:vnRTxewy+M7BtXBNFybkuhSH4WfedVAAnERHgVFhp3k= +cosmossdk.io/schema v0.1.1 h1:I0M6pgI7R10nq+/HCQfbO6BsGBZA8sQy+duR1Y3aKcA= +cosmossdk.io/schema v0.1.1/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= cosmossdk.io/store v1.1.1-0.20240418092142-896cdf1971bc h1:R9O9d75e0qZYUsVV0zzi+D7cNLnX2JrUOQNoIPaF0Bg= cosmossdk.io/store v1.1.1-0.20240418092142-896cdf1971bc/go.mod h1:amTTatOUV3u1PsKmNb87z6/galCxrRbz9kRdJkL0DyU= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= diff --git a/x/staking/go.mod b/x/staking/go.mod index 1d077317e32c..2813f99f9df3 100644 --- a/x/staking/go.mod +++ b/x/staking/go.mod @@ -169,7 +169,10 @@ require ( go.opencensus.io v0.24.0 // indirect ) -require github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect +require ( + cosmossdk.io/schema v0.1.1 // indirect + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect +) replace github.com/cosmos/cosmos-sdk => ../../. diff --git a/x/staking/go.sum b/x/staking/go.sum index 6a55b551b818..1ce5e4221f18 100644 --- a/x/staking/go.sum +++ b/x/staking/go.sum @@ -8,6 +8,8 @@ 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/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE= cosmossdk.io/math v1.3.0/go.mod h1:vnRTxewy+M7BtXBNFybkuhSH4WfedVAAnERHgVFhp3k= +cosmossdk.io/schema v0.1.1 h1:I0M6pgI7R10nq+/HCQfbO6BsGBZA8sQy+duR1Y3aKcA= +cosmossdk.io/schema v0.1.1/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= cosmossdk.io/store v1.1.1-0.20240418092142-896cdf1971bc h1:R9O9d75e0qZYUsVV0zzi+D7cNLnX2JrUOQNoIPaF0Bg= cosmossdk.io/store v1.1.1-0.20240418092142-896cdf1971bc/go.mod h1:amTTatOUV3u1PsKmNb87z6/galCxrRbz9kRdJkL0DyU= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= diff --git a/x/upgrade/go.mod b/x/upgrade/go.mod index 11324a6d7465..a0f9c5e43443 100644 --- a/x/upgrade/go.mod +++ b/x/upgrade/go.mod @@ -44,6 +44,7 @@ require ( cloud.google.com/go/storage v1.42.0 // indirect cosmossdk.io/collections v0.4.0 // indirect cosmossdk.io/math v1.3.0 // indirect + cosmossdk.io/schema v0.1.1 // indirect cosmossdk.io/x/bank v0.0.0-20240226161501-23359a0b6d91 // indirect cosmossdk.io/x/staking v0.0.0-00010101000000-000000000000 // indirect cosmossdk.io/x/tx v0.13.3 // indirect diff --git a/x/upgrade/go.sum b/x/upgrade/go.sum index 0e652402effc..1345b2cb79f4 100644 --- a/x/upgrade/go.sum +++ b/x/upgrade/go.sum @@ -198,6 +198,8 @@ 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/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE= cosmossdk.io/math v1.3.0/go.mod h1:vnRTxewy+M7BtXBNFybkuhSH4WfedVAAnERHgVFhp3k= +cosmossdk.io/schema v0.1.1 h1:I0M6pgI7R10nq+/HCQfbO6BsGBZA8sQy+duR1Y3aKcA= +cosmossdk.io/schema v0.1.1/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= cosmossdk.io/store v1.1.1-0.20240418092142-896cdf1971bc h1:R9O9d75e0qZYUsVV0zzi+D7cNLnX2JrUOQNoIPaF0Bg= cosmossdk.io/store v1.1.1-0.20240418092142-896cdf1971bc/go.mod h1:amTTatOUV3u1PsKmNb87z6/galCxrRbz9kRdJkL0DyU= cosmossdk.io/x/protocolpool v0.0.0-20230925135524-a1bc045b3190 h1:XQJj9Dv9Gtze0l2TF79BU5lkP6MkUveTUuKICmxoz+o=