From e925a63f7961edda08f12efdfeb0a0bba49783f7 Mon Sep 17 00:00:00 2001 From: Freddy Caceres Date: Mon, 12 Jun 2023 13:55:38 +0200 Subject: [PATCH] Upstream changes from v0.46.x (#40) Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> Co-authored-by: Robert Zaremba Co-authored-by: Marko Co-authored-by: Julien Robert Co-authored-by: atheeshp <59333759+atheeshp@users.noreply.github.com> Co-authored-by: yihuang Co-authored-by: Daniel Wedul Co-authored-by: Aleksandr Bezobchuk Co-authored-by: Javier Su Co-authored-by: khanh-notional <50263489+catShaark@users.noreply.github.com> Co-authored-by: mmsqe Co-authored-by: Jeancarlo Barrios Co-authored-by: Facundo Medica --- .gitignore | 1 + CHANGELOG.md | 94 +-- Makefile | 25 +- RELEASE_NOTES.md | 23 +- baseapp/baseapp.go | 24 +- baseapp/circuit.go | 8 + baseapp/msg_service_router.go | 19 + client/{prompts.go => prompt_validation.go} | 17 +- client/prompt_validation_test.go | 38 ++ client/snapshot/cmd.go | 23 + client/snapshot/delete.go | 35 ++ client/snapshot/dump.go | 125 ++++ client/snapshot/export.go | 51 ++ client/snapshot/list.go | 30 + client/snapshot/load.go | 113 ++++ client/snapshot/restore.go | 50 ++ contrib/rosetta/rosetta-ci/data.tar.gz | Bin 44165 -> 47219 bytes docs/.vuepress/config.js | 8 +- docs/run-node/run-node.md | 41 +- go.mod | 92 +-- go.sum | 245 ++++---- proto/cosmos/group/v1/events.proto | 13 + proto/cosmos/group/v1/query.proto | 27 + proto/cosmos/group/v1/types.proto | 5 - proto/cosmos/vesting/v1beta1/tx.proto | 2 + proto/cosmos/vesting/v1beta1/vesting.proto | 3 + scripts/protocgen.sh | 2 - server/start.go | 5 + server/tm_cmds.go | 97 +++ server/types/app.go | 7 + server/util.go | 25 +- simapp/simd/cmd/root.go | 2 + simapp/state.go | 43 +- snapshots/README.md | 23 +- snapshots/manager.go | 103 +++- snapshots/manager_test.go | 7 + snapshots/store.go | 73 ++- store/iavl/store.go | 2 +- store/iavl/store_test.go | 2 +- store/rootmulti/store.go | 25 +- store/rootmulti/store_test.go | 23 +- types/simulation/types.go | 4 + x/auth/vesting/client/cli/tx.go | 2 +- x/auth/vesting/types/msgs.go | 8 + x/auth/vesting/types/tx.pb.go | 10 +- x/auth/vesting/types/vesting.pb.go | 7 +- x/distribution/keeper/delegation.go | 1 + x/distribution/types/events.go | 4 +- x/gov/migrations/v046/convert.go | 2 +- x/group/client/cli/query.go | 35 ++ x/group/client/testutil/query.go | 49 ++ x/group/events.pb.go | 307 +++++++++- x/group/keeper/genesis.go | 3 +- x/group/keeper/grpc_query.go | 23 + x/group/keeper/keeper.go | 17 + x/group/keeper/keeper_test.go | 67 ++- x/group/keeper/msg_server.go | 11 + x/group/query.pb.go | 633 +++++++++++++++++--- x/group/query.pb.gw.go | 83 +++ x/group/simulation/genesis.go | 18 + x/group/spec/04_events.md | 9 + 61 files changed, 2417 insertions(+), 427 deletions(-) create mode 100644 baseapp/circuit.go rename client/{prompts.go => prompt_validation.go} (81%) create mode 100644 client/prompt_validation_test.go create mode 100644 client/snapshot/cmd.go create mode 100644 client/snapshot/delete.go create mode 100644 client/snapshot/dump.go create mode 100644 client/snapshot/export.go create mode 100644 client/snapshot/list.go create mode 100644 client/snapshot/load.go create mode 100644 client/snapshot/restore.go diff --git a/.gitignore b/.gitignore index 1ce4f5cfa123..1adf64472c42 100644 --- a/.gitignore +++ b/.gitignore @@ -23,6 +23,7 @@ dist tools-stamp buf-stamp artifacts +tools/ # Data - ideally these don't exist baseapp/data/* diff --git a/CHANGELOG.md b/CHANGELOG.md index 96a3063c5faa..bbc2e468c8a0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -35,53 +35,73 @@ Ref: https://keepachangelog.com/en/1.0.0/ # Changelog -## [Unreleased] +## [v0.46.13-alpha.ledger.8](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.46.13-alpha.ledger.8) -### Bug Fixes +### Improvements -## [v0.46.11-alpha.ledger.8] +* (x/distribution) [#35](https://github.com/evmos/cosmos-sdk/pull/35) Add `DistributionAuthorization` authz type +* (x/distribution) [#29](https://github.com/evmos/cosmos-sdk/pull/29) Add `Querier` to distribution module. -### Improvements -* (x/distribution) [#35](https://github.com/evmos/cosmos-sdk/pull/35) Add `DistributionAuthorization` authz type +### Bug Fixes +* (x/staking) [#21](https://github.com/evmos/cosmos-sdk/pull/21) Add `CancelUnbondingDelegation` authz. -## [v0.46.11-alpha.ledger.7](https://github.com/evmos/cosmos-sdk/releases/tag/v0.46.11-alpha.ledger.7) - 2022-05-22 -### Improvements +## [v0.46.13](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.46.13) - 2023-06-08 -* (simapp) [#15305](https://github.com/cosmos/cosmos-sdk/pull/15305) Add `AppStateFnWithExtendedCb` with callback function to extend rawState and `AppStateRandomizedFnWithState` with extra genesisState argument which is the genesis state of the app. -* (x/distribution) [#29](https://github.com/evmos/cosmos-sdk/pull/29) Add `Querier` to distribution module. +## Features -## [v0.46.11-alpha.ledger](https://github.com/evmos/cosmos-sdk/releases/tag/v0.46.11-alpha.ledger) - 2022-03-23 +* (snapshots) [#16060](https://github.com/cosmos/cosmos-sdk/pull/16060) Support saving and restoring snapshot locally. +* (baseapp) [#16290](https://github.com/cosmos/cosmos-sdk/pull/16290) Add circuit breaker setter in baseapp. +* (x/group) [#16191](https://github.com/cosmos/cosmos-sdk/pull/16191) Add EventProposalPruned event to group module whenever a proposal is pruned. ### Improvements -* (deps) Migrate to [CometBFT](https://github.com/cometbft/cometbft). Follow the instructions in the [release notes](./RELEASE_NOTES.md). -* (store) [#15152](https://github.com/cosmos/cosmos-sdk/pull/15152) Remove unmaintained and experimental `store/v2alpha1`. +* (deps) [#15973](https://github.com/cosmos/cosmos-sdk/pull/15973) Bump CometBFT to [v0.34.28](https://github.com/cometbft/cometbft/blob/v0.34.28/CHANGELOG.md#v03428). +* (store) [#15683](https://github.com/cosmos/cosmos-sdk/pull/15683) `rootmulti.Store.CacheMultiStoreWithVersion` now can handle loading archival states that don't persist any of the module stores the current state has. +* (simapp) [#15903](https://github.com/cosmos/cosmos-sdk/pull/15903) Add `AppStateFnWithExtendedCbs` with moduleStateCb callback function to allow access moduleState. Note, this function is present in `simtestutil` from `v0.47.2+`. +* (gov) [#15979](https://github.com/cosmos/cosmos-sdk/pull/15979) Improve gov error message when failing to convert v1 proposal to v1beta1. +* (server) [#16061](https://github.com/cosmos/cosmos-sdk/pull/16061) Add Comet bootstrap command. +* (store) [#16067](https://github.com/cosmos/cosmos-sdk/pull/16067) Add local snapshots management commands. +* (baseapp) [#16193](https://github.com/cosmos/cosmos-sdk/pull/16193) Add `Close` method to `BaseApp` for custom app to cleanup resource in graceful shutdown. ### Bug Fixes -* [#15243](https://github.com/cosmos/cosmos-sdk/pull/15243) `LatestBlockResponse` & `BlockByHeightResponse` types' field `sdk_block` was incorrectly cast `proposer_address` bytes to validator operator address, now to consensus address. -* (x/auth/vesting) [#15383](https://github.com/cosmos/cosmos-sdk/pull/15383) Add extra checks when creating a periodic vesting account. -* (x/staking) [#21](https://github.com/evmos/cosmos-sdk/pull/21) Add `CancelUnbondingDelegation` authz. +* Fix [barberry](https://forum.cosmos.network/t/cosmos-sdk-security-advisory-barberry/10825) security vulnerability. +* (cli) [#16312](https://github.com/cosmos/cosmos-sdk/pull/16312) Allow any addresses in `client.ValidatePromptAddress`. +* (store/iavl) [#15717](https://github.com/cosmos/cosmos-sdk/pull/15717) Upstream error on empty version (this change was present on all version but v0.46). -## [v0.46.10-alpha.ledger.2](https://github.com/evmos/cosmos-sdk/releases/tag/v0.46.10-alpha.ledger.2) - 2023-03-15 +## [v0.46.12](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.46.12) - 2023-04-04 + +### Features + +* (x/groups) [#14879](https://github.com/cosmos/cosmos-sdk/pull/14879) Add `Query/Groups` query to get all the groups. ### Improvements -* (release) [#26](https://github.com/evmos/cosmos-sdk/pull/26) Change naming convention to keep reference of underlying cosmos-sdk version +* (simapp) [#15305](https://github.com/cosmos/cosmos-sdk/pull/15305) Add `AppStateFnWithExtendedCb` with callback function to extend rawState and `AppStateRandomizedFnWithState` with extra genesisState argument which is the genesis state of the app. +* (x/distribution) [#15462](https://github.com/cosmos/cosmos-sdk/pull/15462) Add delegator address to the event for withdrawing delegation rewards +* [#14019](https://github.com/cosmos/cosmos-sdk/issues/14019) Remove the interface casting to allow other implementations of a `CommitMultiStore`. ### Bug Fixes -* (cli) [#22](https://github.com/evmos/cosmos-sdk/pull/22) Rollback `--fees auto` flag +* (x/auth/vesting) [#15383](https://github.com/cosmos/cosmos-sdk/pull/15383) Add extra checks when creating a periodic vesting account. +* (x/gov) [#13051](https://github.com/cosmos/cosmos-sdk/pull/13051) In SubmitPropsal, when a legacy msg fails it's handler call, wrap the error as ErrInvalidProposalContent (instead of ErrNoProposalHandlerExists). + +## [v0.46.11](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.46.11) - 2023-03-03 -## [v0.46.10-alpha.ledger.1](https://github.com/evmos/cosmos-sdk/releases/tag/v0.46.10-alpha.ledger.1) - 2023-03-15 +### Improvements + +* (deps) Migrate to [CometBFT](https://github.com/cometbft/cometbft). Follow the instructions in the [release notes](./RELEASE_NOTES.md). +* (store) [#15152](https://github.com/cosmos/cosmos-sdk/pull/15152) Remove unmaintained and experimental `store/v2alpha1`. ### Bug Fixes -* (cli) [#16](https://github.com/evmos/cosmos-sdk/pull/16) Set `--fees` flag default value to empty string +* [#15243](https://github.com/cosmos/cosmos-sdk/pull/15243) `LatestBlockResponse` & `BlockByHeightResponse` types' field `sdk_block` was incorrectly cast `proposer_address` bytes to validator operator address, now to consensus address. +* (x/auth/vesting) [#15383](https://github.com/cosmos/cosmos-sdk/pull/15383) Add extra checks when creating a periodic vesting account. +* (x/staking) [#21](https://github.com/evmos/cosmos-sdk/pull/21) Add `CancelUnbondingDelegation` authz. -## [v0.46.10-ledger](https://github.com/evmos/cosmos-sdk/releases/tag/v0.46.10-ledger) - 2023-02-24 +## [v0.46.10](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.46.10) - 2023-02-16 ### Improvements @@ -90,19 +110,19 @@ Ref: https://keepachangelog.com/en/1.0.0/ * (cli) [#8](https://github.com/evmos/cosmos-sdk/pull/8) Add `auto` option for fees flag * (grpc) [#13144](https://github.com/cosmos/cosmos-sdk/pull/13144) Add validator distribution info grpc gateway get endpoint. -## [v0.46.9](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.46.9) - 2022-02-07 +## [v0.46.9](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.46.9) - 2023-02-07 ### Improvements * (deps) [#14846](https://github.com/cosmos/cosmos-sdk/pull/14846) Bump btcd. * (deps) Bump Tendermint version to [v0.34.26](https://github.com/informalsystems/tendermint/releases/tag/v0.34.26). * (store) [#14189](https://github.com/cosmos/cosmos-sdk/pull/14189) Add config `iavl-lazy-loading` to enable lazy loading of iavl store, to improve start up time of archive nodes, add method `SetLazyLoading` to `CommitMultiStore` interface. - * A new field has been added to the app.toml. This alllows nodes with larger databases to startup quicker + * A new field has been added to the app.toml. This alllows nodes with larger databases to startup quicker ```toml # IAVLLazyLoading enable/disable the lazy loading of iavl store. # Default is false. - iavl-lazy-loading = "" + iavl-lazy-loading = "" ``` ### Bug Fixes @@ -138,7 +158,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ * (deps) Bump Tendermint version to [v0.34.24](https://github.com/tendermint/tendermint/releases/tag/v0.34.24). * [#13651](https://github.com/cosmos/cosmos-sdk/pull/13651) Update `server/config/config.GetConfig` function. -* [#14175](https://github.com/cosmos/cosmos-sdk/pull/14175) Add `server.DefaultBaseappOptions(appopts)` function to reduce boiler plate in root.go. +* [#14175](https://github.com/cosmos/cosmos-sdk/pull/14175) Add `server.DefaultBaseappOptions(appopts)` function to reduce boiler plate in root.go. ### State Machine Breaking @@ -228,7 +248,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ ATTENTION: -This is a security release for the [Dragonberry security advisory](https://forum.cosmos.network/t/ibc-security-advisory-dragonberry/7702). +This is a security release for the [Dragonberry security advisory](https://forum.cosmos.network/t/ibc-security-advisory-dragonberry/7702). All users should upgrade immediately. @@ -267,7 +287,7 @@ replace github.com/confio/ics23/go => github.com/cosmos/cosmos-sdk/ics23/go v0.8 ### API Breaking Changes -* (cli) [#13089](https://github.com/cosmos/cosmos-sdk/pull/13089) Fix rollback command don't actually delete multistore versions, added method `RollbackToVersion` to interface `CommitMultiStore` and added method `CommitMultiStore` to `Application` interface. +* (cli) [#13089](https://github.com/cosmos/cosmos-sdk/pull/13089) Fix rollback command don't actually delete multistore versions, added method `RollbackToVersion` to interface `CommitMultiStore` and added method `CommitMultiStore` to `Application` interface. * (cli) [#13089](https://github.com/cosmos/cosmos-sdk/pull/13089) `NewRollbackCmd` now takes an `appCreator types.AppCreator`. ### Features @@ -286,8 +306,8 @@ replace github.com/confio/ics23/go => github.com/cosmos/cosmos-sdk/ics23/go v0.8 * (x/group) [#13214](https://github.com/cosmos/cosmos-sdk/pull/13214) Add `withdraw-proposal` command to group module's CLI transaction commands. * (x/auth) [#13048](https://github.com/cosmos/cosmos-sdk/pull/13048) Add handling of AccountNumberStoreKeyPrefix to the simulation decoder. * (simapp) [#13108](https://github.com/cosmos/cosmos-sdk/pull/13108) Call `SetIAVLCacheSize` with the configured value in simapp. -* [#13318](https://github.com/cosmos/cosmos-sdk/pull/13318) Keep the balance query endpoint compatible with legacy blocks. -* [#13321](https://github.com/cosmos/cosmos-sdk/pull/13321) Add flag to disable fast node migration and usage. +* [#13318](https://github.com/cosmos/cosmos-sdk/pull/13318) Keep the balance query endpoint compatible with legacy blocks. +* [#13321](https://github.com/cosmos/cosmos-sdk/pull/13321) Add flag to disable fast node migration and usage. ### Bug Fixes @@ -295,15 +315,15 @@ replace github.com/confio/ics23/go => github.com/cosmos/cosmos-sdk/ics23/go v0.8 * (x/auth) [#13200](https://github.com/cosmos/cosmos-sdk/pull/13200) Fix wrong sequences in `sign-batch`. * (export) [#13029](https://github.com/cosmos/cosmos-sdk/pull/13029) Fix exporting the blockParams regression. * [#13046](https://github.com/cosmos/cosmos-sdk/pull/13046) Fix missing return statement in BaseApp.Query. -* (store) [#13336](https://github.com/cosmos/cosmos-sdk/pull/13336) Call streaming listeners for deliver tx event, it was removed accidentally, backport #13334. -* (grpc) [#13417](https://github.com/cosmos/cosmos-sdk/pull/13417) fix grpc query panic that could crash the node (backport #13352). +* (store) [#13336](https://github.com/cosmos/cosmos-sdk/pull/13336) Call streaming listeners for deliver tx event, it was removed accidentally, backport #13334. +* (grpc) [#13417](https://github.com/cosmos/cosmos-sdk/pull/13417) fix grpc query panic that could crash the node (backport #13352). * (grpc) [#13418](https://github.com/cosmos/cosmos-sdk/pull/13418) Add close for grpc only mode. ## [v0.46.1](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.46.1) - 2022-08-24 ### Improvements -* [#12953](https://github.com/cosmos/cosmos-sdk/pull/12953) Change the default priority mechanism to be based on gas price. +* [#12953](https://github.com/cosmos/cosmos-sdk/pull/12953) Change the default priority mechanism to be based on gas price. * [#12981](https://github.com/cosmos/cosmos-sdk/pull/12981) Return proper error when parsing telemetry configuration. * [#12969](https://github.com/cosmos/cosmos-sdk/pull/12969) Bump Tendermint to `v0.34.21` and IAVL to `v0.19.1`. * [#12885](https://github.com/cosmos/cosmos-sdk/pull/12885) Amortize cost of processing cache KV store. @@ -316,7 +336,7 @@ replace github.com/confio/ics23/go => github.com/cosmos/cosmos-sdk/ics23/go v0.8 ### Bug Fixes * (x/group) [#12888](https://github.com/cosmos/cosmos-sdk/pull/12888) Fix event propagation to the current context of `x/group` message execution `[]sdk.Result`. -* (x/upgrade) [#12906](https://github.com/cosmos/cosmos-sdk/pull/12906) Fix upgrade failure by moving downgrade verification logic after store migration. +* (x/upgrade) [#12906](https://github.com/cosmos/cosmos-sdk/pull/12906) Fix upgrade failure by moving downgrade verification logic after store migration. * (store) [#12945](https://github.com/cosmos/cosmos-sdk/pull/12945) Fix nil end semantics in store/cachekv/iterator when iterating a dirty cache. ## [v0.46.0](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.46.0) - 2022-07-26 @@ -508,7 +528,7 @@ replace github.com/confio/ics23/go => github.com/cosmos/cosmos-sdk/ics23/go v0.8 * (x/auth) [\#11482](https://github.com/cosmos/cosmos-sdk/pull/11482) Improve panic message when attempting to register a method handler for a message that does not implement sdk.Msg * (x/staking) [\#11596](https://github.com/cosmos/cosmos-sdk/pull/11596) Add (re)delegation getters * (errors) [\#11960](https://github.com/cosmos/cosmos-sdk/pull/11960) Removed 'redacted' error message from defaultErrEncoder -* (ante) [#12013](https://github.com/cosmos/cosmos-sdk/pull/12013) Index ante events for failed tx. +* (ante) [#12013](https://github.com/cosmos/cosmos-sdk/pull/12013) Index ante events for failed tx. * [#12668](https://github.com/cosmos/cosmos-sdk/pull/12668) Add `authz_msg_index` event attribute to message events emitted when executing via `MsgExec` through `x/authz`. * [#12626](https://github.com/cosmos/cosmos-sdk/pull/12626) Upgrade IAVL to v0.19.0 with fast index and error propagation. NOTE: first start will take a while to propagate into new model. * [#12649](https://github.com/cosmos/cosmos-sdk/pull/12649) Bump tendermint to v0.34.20. @@ -585,7 +605,7 @@ replace github.com/confio/ics23/go => github.com/cosmos/cosmos-sdk/ics23/go v0.8 * (x/mint) [#12384](https://github.com/cosmos/cosmos-sdk/pull/12384) Ensure `GoalBonded` must be positive when performing `x/mint` parameter validation. * (x/auth) [#12261](https://github.com/cosmos/cosmos-sdk/pull/12261) Deprecate pagination in GetTxsEventRequest/Response in favor of page and limit to align with tendermint `SignClient.TxSearch` * (vesting) [#12190](https://github.com/cosmos/cosmos-sdk/pull/12190) Replace https://github.com/cosmos/cosmos-sdk/pull/12190 to use `NewBaseAccountWithAddress` in all vesting account message handlers. -* (linting) [#12135](https://github.com/cosmos/cosmos-sdk/pull/12135/) Fix variable naming issues per enabled linters. Run gofumpt to ensure easy reviews of ongoing linting work. +* (linting) [#12135](https://github.com/cosmos/cosmos-sdk/pull/12135/) Fix variable naming issues per enabled linters. Run gofumpt to ensure easy reviews of ongoing linting work. * (linting) [#12132](https://github.com/cosmos/cosmos-sdk/pull/12132) Change sdk.Int to math.Int, run `gofumpt -w -l .`, and `golangci-lint run ./... --fix` * (cli) [#12127](https://github.com/cosmos/cosmos-sdk/pull/12127) Fix the CLI not always taking into account `--fee-payer` and `--fee-granter` flags. * (migrations) [#12028](https://github.com/cosmos/cosmos-sdk/pull/12028) Fix v0.45->v0.46 in-place store migrations. @@ -611,7 +631,7 @@ replace github.com/confio/ics23/go => github.com/cosmos/cosmos-sdk/ics23/go v0.8 * (x/upgrade) [\#10189](https://github.com/cosmos/cosmos-sdk/issues/10189) Removed potential sources of non-determinism in upgrades * [\#10422](https://github.com/cosmos/cosmos-sdk/pull/10422) and [\#10529](https://github.com/cosmos/cosmos-sdk/pull/10529) Add `MinCommissionRate` param to `x/staking` module. * (x/gov) [#10763](https://github.com/cosmos/cosmos-sdk/pull/10763) modify the fields in `TallyParams` to use `string` instead of `bytes` -* [#10770](https://github.com/cosmos/cosmos-sdk/pull/10770) revert tx when block gas limit exceeded +* [#10770](https://github.com/cosmos/cosmos-sdk/pull/10770) revert tx when block gas limit exceeded * (x/gov) [\#10868](https://github.com/cosmos/cosmos-sdk/pull/10868) Bump gov to v1beta2. Both v1beta1 and v1beta2 queries and Msgs are accepted. * [\#11011](https://github.com/cosmos/cosmos-sdk/pull/11011) Remove burning of deposits when qourum is not reached on a governance proposal and when the deposit is not fully met. * [\#11019](https://github.com/cosmos/cosmos-sdk/pull/11019) Add `MsgCreatePermanentLockedAccount` and CLI method for creating permanent locked account @@ -620,7 +640,7 @@ replace github.com/confio/ics23/go => github.com/cosmos/cosmos-sdk/ics23/go v0.8 * (x/feegrant) [\#10830](https://github.com/cosmos/cosmos-sdk/pull/10830) Expired allowances will be pruned from state. * (x/authz,x/feegrant) [\#11214](https://github.com/cosmos/cosmos-sdk/pull/11214) Fix Amino JSON encoding of authz and feegrant Msgs to be consistent with other modules. * (authz)[\#11060](https://github.com/cosmos/cosmos-sdk/pull/11060) Support grant with no expire time. -* (x/gov) [\#10868](https://github.com/cosmos/cosmos-sdk/pull/10868) Bump gov to v1. +* (x/gov) [\#10868](https://github.com/cosmos/cosmos-sdk/pull/10868) Bump gov to v1. ### Deprecated diff --git a/Makefile b/Makefile index dff5e166c762..464ed932482f 100644 --- a/Makefile +++ b/Makefile @@ -15,9 +15,6 @@ DOCKER := $(shell which docker) DOCKER_BUF := $(DOCKER) run --rm -v $(CURDIR):/workspace --workdir /workspace bufbuild/buf:1.0.0-rc8 PROJECT_NAME = $(shell git remote get-url origin | xargs basename -s .git) DOCS_DOMAIN=docs.cosmos.network -# RocksDB is a native dependency, so we don't assume the library is installed. -# Instead, it must be explicitly enabled and we warn when it is not. -ENABLE_ROCKSDB ?= false export GO111MODULE = on @@ -63,33 +60,23 @@ ldflags = -X github.com/cosmos/cosmos-sdk/version.Name=sim \ -X github.com/cosmos/cosmos-sdk/version.Version=$(VERSION) \ -X github.com/cosmos/cosmos-sdk/version.Commit=$(COMMIT) \ -X "github.com/cosmos/cosmos-sdk/version.BuildTags=$(build_tags_comma_sep)" \ - -X github.com/tendermint/tendermint/version.TMCoreSemVer=$(TMVERSION) - -ifeq ($(ENABLE_ROCKSDB),true) - BUILD_TAGS += rocksdb_build - test_tags += rocksdb_build -else - $(warning RocksDB support is disabled; to build and test with RocksDB support, set ENABLE_ROCKSDB=true) -endif + -X github.com/tendermint/tendermint/version.TMCoreSemVer=$(TMVERSION) # DB backend selection ifeq (cleveldb,$(findstring cleveldb,$(COSMOS_BUILD_OPTIONS))) build_tags += gcc endif ifeq (badgerdb,$(findstring badgerdb,$(COSMOS_BUILD_OPTIONS))) - BUILD_TAGS += badgerdb + build_tags += badgerdb endif # handle rocksdb ifeq (rocksdb,$(findstring rocksdb,$(COSMOS_BUILD_OPTIONS))) - ifneq ($(ENABLE_ROCKSDB),true) - $(error Cannot use RocksDB backend unless ENABLE_ROCKSDB=true) - endif CGO_ENABLED=1 - BUILD_TAGS += rocksdb + build_tags += rocksdb endif # handle boltdb ifeq (boltdb,$(findstring boltdb,$(COSMOS_BUILD_OPTIONS))) - BUILD_TAGS += boltdb + build_tags += boltdb endif ifeq (,$(findstring nostrip,$(COSMOS_BUILD_OPTIONS))) @@ -406,6 +393,7 @@ proto-gen: @echo "Generating Protobuf files" @if docker ps -a --format '{{.Names}}' | grep -Eq "^${containerProtoGen}$$"; then docker start -a $(containerProtoGen); else docker run --name $(containerProtoGen) -v $(CURDIR):/workspace --workdir /workspace $(protoImageName) \ sh ./scripts/protocgen.sh; fi + @go mod tidy # This generates the SDK's custom wrapper for google.protobuf.Any. It should only be run manually when needed proto-gen-any: @@ -423,14 +411,13 @@ proto-format: @if docker ps -a --format '{{.Names}}' | grep -Eq "^${containerProtoFmt}$$"; then docker start -a $(containerProtoFmt); else docker run --name $(containerProtoFmt) -v $(CURDIR):/workspace --workdir /workspace tendermintdev/docker-build-proto \ find ./ -not -path "./third_party/*" -name "*.proto" -exec clang-format -i {} \; ; fi - proto-lint: @$(DOCKER_BUF) lint --error-format=json proto-check-breaking: @$(DOCKER_BUF) breaking --against $(HTTPS_GIT)#branch=main -TM_URL = https://raw.githubusercontent.com/cometbft/cometbft/v0.34.27/proto/tendermint +TM_URL = https://raw.githubusercontent.com/cometbft/cometbft/v0.34.28/proto/tendermint TM_CRYPTO_TYPES = proto/tendermint/crypto TM_ABCI_TYPES = proto/tendermint/abci diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 381bb7ca8b0f..27610b6ec13a 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,18 +1,21 @@ -# Cosmos SDK v0.46.11 Release Notes +# Cosmos SDK v0.46.13 Release Notes -This release includes the migration to [CometBFT v0.34.27](https://github.com/cometbft/cometbft/blob/v0.34.27/CHANGELOG.md#v03427). -This migration should be not be breaking for chains. -From `v0.46.11`+, the following replace is *mandatory* in the `go.mod` of your application: +This release includes few improvements and bug fixes. +Notably, the [barberry security fix](https://forum.cosmos.network/t/cosmos-sdk-security-advisory-barberry/10825). All chains using Cosmos SDK v0.46.0 and above must upgrade to `v0.46.13` **immediately**. A chain is safe as soon as **33%+1** of the voting power has upgraded. Coordinate with your validators to upgrade as soon as possible. + +Additionally, it includes new commands for snapshots management and bootstrapping from a local snapshot (add `snapshot.Cmd(appCreator)` to the chain root command for using it). + +Did you know Cosmos SDK Twilight (a.k.a v0.47) has been released? Upgrade easily by reading the [upgrading guide](https://github.com/cosmos/cosmos-sdk/blob/release/v0.47.x/UPGRADING.md#v047x). + +Ensure you have the following replaces in the `go.mod` of your application: ```go // use cometbft -replace github.com/tendermint/tendermint => github.com/cometbft/cometbft v0.34.27 +replace github.com/tendermint/tendermint => github.com/cometbft/cometbft v0.34.28 +// replace broken goleveldb +replace github.com/syndtr/goleveldb => github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 ``` -Additionally, the SDK sets its minimum version to Go 1.19. This is not because the SDK uses new Go 1.19 functionalities, but to signal that we recommend chains to upgrade to Go 1.19 — Go 1.18 is not supported by the Go Team anymore. -Note, that SDK recommends chains to use the same Go version across all of their network. -We recommend, as well, chains to perform a **coordinated upgrade** when migrating from Go 1.18 to Go 1.19. - Please see the [CHANGELOG](https://github.com/cosmos/cosmos-sdk/blob/release/v0.46.x/CHANGELOG.md) for an exhaustive list of changes. -**Full Commit History**: https://github.com/cosmos/cosmos-sdk/compare/v0.46.10...v0.46.11 +**Full Commit History**: https://github.com/cosmos/cosmos-sdk/compare/v0.46.12...v0.46.13 diff --git a/baseapp/baseapp.go b/baseapp/baseapp.go index 78d57763726e..b42a56efca68 100644 --- a/baseapp/baseapp.go +++ b/baseapp/baseapp.go @@ -1,6 +1,7 @@ package baseapp import ( + "errors" "fmt" "strings" @@ -14,7 +15,6 @@ import ( codectypes "github.com/cosmos/cosmos-sdk/codec/types" "github.com/cosmos/cosmos-sdk/snapshots" "github.com/cosmos/cosmos-sdk/store" - "github.com/cosmos/cosmos-sdk/store/rootmulti" storetypes "github.com/cosmos/cosmos-sdk/store/types" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" @@ -229,6 +229,15 @@ func (app *BaseApp) SetMsgServiceRouter(msgServiceRouter *MsgServiceRouter) { app.msgServiceRouter = msgServiceRouter } +// SetCircuitBreaker sets the circuit breaker for the BaseApp. +// The circuit breaker is checked on every message execution to verify if a transaction should be executed or not. +func (app *BaseApp) SetCircuitBreaker(cb CircuitBreaker) { + if app.msgServiceRouter == nil { + panic("cannot set circuit breaker with no msg service router set") + } + app.msgServiceRouter.SetCircuit(cb) +} + // MountStores mounts all IAVL or DB stores to the provided keys in the BaseApp // multistore. func (app *BaseApp) MountStores(keys ...storetypes.StoreKey) { @@ -352,11 +361,11 @@ func (app *BaseApp) Init() error { app.setCheckState(tmproto.Header{}) app.Seal() - rms, ok := app.cms.(*rootmulti.Store) - if !ok { - return fmt.Errorf("invalid commit multi-store; expected %T, got: %T", &rootmulti.Store{}, app.cms) + if app.cms == nil { + return errors.New("commit multi-store must not be nil") } - return rms.GetPruning().Validate() + + return app.cms.GetPruning().Validate() } func (app *BaseApp) setMinGasPrices(gasPrices sdk.DecCoins) { @@ -844,3 +853,8 @@ func (app *BaseApp) runMsgs(ctx sdk.Context, msgs []sdk.Msg, mode runTxMode) (*s func makeABCIData(msgResponses []*codectypes.Any) ([]byte, error) { return proto.Marshal(&sdk.TxMsgData{MsgResponses: msgResponses}) } + +// Close is called in start cmd to gracefully cleanup resources. +func (app *BaseApp) Close() error { + return nil +} diff --git a/baseapp/circuit.go b/baseapp/circuit.go new file mode 100644 index 000000000000..3db0bc1bdcda --- /dev/null +++ b/baseapp/circuit.go @@ -0,0 +1,8 @@ +package baseapp + +import "context" + +// CircuitBreaker is an interface that defines the methods for a circuit breaker. +type CircuitBreaker interface { + IsAllowed(ctx context.Context, typeURL string) (bool, error) +} diff --git a/baseapp/msg_service_router.go b/baseapp/msg_service_router.go index b42fc282ec31..b70864ddd287 100644 --- a/baseapp/msg_service_router.go +++ b/baseapp/msg_service_router.go @@ -17,6 +17,7 @@ import ( type MsgServiceRouter struct { interfaceRegistry codectypes.InterfaceRegistry routes map[string]MsgServiceHandler + circuitBreaker CircuitBreaker } var _ gogogrpc.Server = &MsgServiceRouter{} @@ -31,6 +32,10 @@ func NewMsgServiceRouter() *MsgServiceRouter { // MsgServiceHandler defines a function type which handles Msg service message. type MsgServiceHandler = func(ctx sdk.Context, req sdk.Msg) (*sdk.Result, error) +func (msr *MsgServiceRouter) SetCircuit(cb CircuitBreaker) { + msr.circuitBreaker = cb +} + // Handler returns the MsgServiceHandler for a given msg or nil if not found. func (msr *MsgServiceRouter) Handler(msg sdk.Msg) MsgServiceHandler { return msr.routes[sdk.MsgTypeURL(msg)] @@ -121,6 +126,20 @@ func (msr *MsgServiceRouter) RegisterService(sd *grpc.ServiceDesc, handler inter return nil, err } } + + if msr.circuitBreaker != nil { + msgURL := sdk.MsgTypeURL(req) + + isAllowed, err := msr.circuitBreaker.IsAllowed(ctx, msgURL) + if err != nil { + return nil, err + } + + if !isAllowed { + return nil, fmt.Errorf("circuit breaker disables execution of this message: %s", msgURL) + } + } + // Call the method handler from the service description with the handler object. // We don't do any decoding here because the decoding was already done. res, err := methodHandler(handler, sdk.WrapSDKContext(ctx), noopDecoder, interceptor) diff --git a/client/prompts.go b/client/prompt_validation.go similarity index 81% rename from client/prompts.go rename to client/prompt_validation.go index 050d806c49a8..d3e3e2321726 100644 --- a/client/prompts.go +++ b/client/prompt_validation.go @@ -29,11 +29,22 @@ func ValidatePromptURL(input string) error { // ValidatePromptAddress validates that the input is a valid Bech32 address. func ValidatePromptAddress(input string) error { - if _, err := sdk.AccAddressFromBech32(input); err != nil { - return fmt.Errorf("invalid address: %w", err) + _, err := sdk.AccAddressFromBech32(input) + if err == nil { + return nil } - return nil + _, err = sdk.ValAddressFromBech32(input) + if err == nil { + return nil + } + + _, err = sdk.ConsAddressFromBech32(input) + if err == nil { + return nil + } + + return fmt.Errorf("invalid address: %w", err) } // ValidatePromptYesNo validates that the input is valid sdk.COins diff --git a/client/prompt_validation_test.go b/client/prompt_validation_test.go new file mode 100644 index 000000000000..eba30c21c441 --- /dev/null +++ b/client/prompt_validation_test.go @@ -0,0 +1,38 @@ +package client_test + +import ( + "testing" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/stretchr/testify/require" +) + +func TestValidatePromptNotEmpty(t *testing.T) { + require := require.New(t) + + require.NoError(client.ValidatePromptNotEmpty("foo")) + require.ErrorContains(client.ValidatePromptNotEmpty(""), "input cannot be empty") +} + +func TestValidatePromptURL(t *testing.T) { + require := require.New(t) + + require.NoError(client.ValidatePromptURL("https://example.com")) + require.ErrorContains(client.ValidatePromptURL("foo"), "invalid URL") +} + +func TestValidatePromptAddress(t *testing.T) { + require := require.New(t) + + require.NoError(client.ValidatePromptAddress("cosmos1huydeevpz37sd9snkgul6070mstupukw00xkw9")) + require.NoError(client.ValidatePromptAddress("cosmosvaloper1sjllsnramtg3ewxqwwrwjxfgc4n4ef9u2lcnj0")) + require.NoError(client.ValidatePromptAddress("cosmosvalcons1ntk8eualewuprz0gamh8hnvcem2nrcdsgz563h")) + require.ErrorContains(client.ValidatePromptAddress("foo"), "invalid address") +} + +func TestValidatePromptCoins(t *testing.T) { + require := require.New(t) + + require.NoError(client.ValidatePromptCoins("100stake")) + require.ErrorContains(client.ValidatePromptCoins("foo"), "invalid coins") +} diff --git a/client/snapshot/cmd.go b/client/snapshot/cmd.go new file mode 100644 index 000000000000..14388bc8d05e --- /dev/null +++ b/client/snapshot/cmd.go @@ -0,0 +1,23 @@ +package snapshot + +import ( + servertypes "github.com/cosmos/cosmos-sdk/server/types" + "github.com/spf13/cobra" +) + +// Cmd returns the snapshots group command +func Cmd(appCreator servertypes.AppCreator) *cobra.Command { + cmd := &cobra.Command{ + Use: "snapshots", + Short: "Manage local snapshots", + } + cmd.AddCommand( + ListSnapshotsCmd, + RestoreSnapshotCmd(appCreator), + ExportSnapshotCmd(appCreator), + DumpArchiveCmd(), + LoadArchiveCmd(), + DeleteSnapshotCmd(), + ) + return cmd +} diff --git a/client/snapshot/delete.go b/client/snapshot/delete.go new file mode 100644 index 000000000000..0259032e1134 --- /dev/null +++ b/client/snapshot/delete.go @@ -0,0 +1,35 @@ +package snapshot + +import ( + "strconv" + + "github.com/cosmos/cosmos-sdk/server" + "github.com/spf13/cobra" +) + +func DeleteSnapshotCmd() *cobra.Command { + return &cobra.Command{ + Use: "delete ", + Short: "Delete a local snapshot", + Args: cobra.ExactArgs(2), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := server.GetServerContextFromCmd(cmd) + + height, err := strconv.ParseUint(args[0], 10, 64) + if err != nil { + return err + } + format, err := strconv.ParseUint(args[1], 10, 32) + if err != nil { + return err + } + + snapshotStore, err := server.GetSnapshotStore(ctx.Viper) + if err != nil { + return err + } + + return snapshotStore.Delete(height, uint32(format)) + }, + } +} diff --git a/client/snapshot/dump.go b/client/snapshot/dump.go new file mode 100644 index 000000000000..72dadbc57254 --- /dev/null +++ b/client/snapshot/dump.go @@ -0,0 +1,125 @@ +package snapshot + +import ( + "archive/tar" + "compress/gzip" + "errors" + "fmt" + "io" + "os" + "strconv" + + "github.com/cosmos/cosmos-sdk/server" + "github.com/spf13/cobra" +) + +// DumpArchiveCmd returns a command to dump the snapshot as portable archive format +func DumpArchiveCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "dump ", + Short: "Dump the snapshot as portable archive format", + Args: cobra.ExactArgs(2), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := server.GetServerContextFromCmd(cmd) + snapshotStore, err := server.GetSnapshotStore(ctx.Viper) + if err != nil { + return err + } + + output, err := cmd.Flags().GetString("output") + if err != nil { + return err + } + + height, err := strconv.ParseUint(args[0], 10, 64) + if err != nil { + return err + } + format, err := strconv.ParseUint(args[1], 10, 32) + if err != nil { + return err + } + + if output == "" { + output = fmt.Sprintf("%d-%d.tar.gz", height, format) + } + + snapshot, err := snapshotStore.Get(height, uint32(format)) + if err != nil { + return err + } + + if snapshot == nil { + return errors.New("snapshot doesn't exist") + } + + bz, err := snapshot.Marshal() + if err != nil { + return err + } + + fp, err := os.Create(output) + if err != nil { + return err + } + defer fp.Close() + + // since the chunk files are already compressed, we just use fastest compression here + gzipWriter, err := gzip.NewWriterLevel(fp, gzip.BestSpeed) + if err != nil { + return err + } + tarWriter := tar.NewWriter(gzipWriter) + if err := tarWriter.WriteHeader(&tar.Header{ + Name: SnapshotFileName, + Mode: 0o644, + Size: int64(len(bz)), + }); err != nil { + return fmt.Errorf("failed to write snapshot header to tar: %w", err) + } + if _, err := tarWriter.Write(bz); err != nil { + return fmt.Errorf("failed to write snapshot to tar: %w", err) + } + + for i := uint32(0); i < snapshot.Chunks; i++ { + path := snapshotStore.PathChunk(height, uint32(format), i) + file, err := os.Open(path) + if err != nil { + return fmt.Errorf("failed to open chunk file %s: %w", path, err) + } + defer file.Close() + + st, err := file.Stat() + if err != nil { + return fmt.Errorf("failed to stat chunk file %s: %w", path, err) + } + + if err := tarWriter.WriteHeader(&tar.Header{ + Name: strconv.FormatUint(uint64(i), 10), + Mode: 0o644, + Size: st.Size(), + }); err != nil { + return fmt.Errorf("failed to write chunk header to tar: %w", err) + } + + if _, err := io.Copy(tarWriter, file); err != nil { + return fmt.Errorf("failed to write chunk to tar: %w", err) + } + } + + if err := tarWriter.Close(); err != nil { + return fmt.Errorf("failed to close tar writer: %w", err) + } + + if err := gzipWriter.Close(); err != nil { + return fmt.Errorf("failed to close gzip writer: %w", err) + } + + return fp.Close() + }, + } + + cmd.Flags().StringP("output", "o", "", "output file") + + return cmd +} diff --git a/client/snapshot/export.go b/client/snapshot/export.go new file mode 100644 index 000000000000..cb6ebc1417a4 --- /dev/null +++ b/client/snapshot/export.go @@ -0,0 +1,51 @@ +package snapshot + +import ( + "github.com/cosmos/cosmos-sdk/server" + servertypes "github.com/cosmos/cosmos-sdk/server/types" + "github.com/spf13/cobra" +) + +// ExportSnapshotCmd returns a command to take a snapshot of the application state +func ExportSnapshotCmd(appCreator servertypes.AppCreator) *cobra.Command { + cmd := &cobra.Command{ + Use: "export", + Short: "Export app state to snapshot store", + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := server.GetServerContextFromCmd(cmd) + + height, err := cmd.Flags().GetInt64("height") + if err != nil { + return err + } + + home := ctx.Config.RootDir + db, err := openDB(home, server.GetAppDBBackend(ctx.Viper)) + if err != nil { + return err + } + + app := appCreator(ctx.Logger, db, nil, ctx.Viper) + + if height == 0 { + height = app.CommitMultiStore().LastCommitID().Version + } + + cmd.Printf("Exporting snapshot for height %d\n", height) + + sm := app.SnapshotManager() + snapshot, err := sm.Create(uint64(height)) + if err != nil { + return err + } + + cmd.Printf("Snapshot created at height %d, format %d, chunks %d\n", snapshot.Height, snapshot.Format, snapshot.Chunks) + return nil + }, + } + + cmd.Flags().Int64("height", 0, "Height to export, default to latest state height") + + return cmd +} diff --git a/client/snapshot/list.go b/client/snapshot/list.go new file mode 100644 index 000000000000..78612bf916ee --- /dev/null +++ b/client/snapshot/list.go @@ -0,0 +1,30 @@ +package snapshot + +import ( + "fmt" + + "github.com/cosmos/cosmos-sdk/server" + "github.com/spf13/cobra" +) + +// ListSnapshotsCmd returns the command to list local snapshots +var ListSnapshotsCmd = &cobra.Command{ + Use: "list", + Short: "List local snapshots", + RunE: func(cmd *cobra.Command, args []string) error { + ctx := server.GetServerContextFromCmd(cmd) + snapshotStore, err := server.GetSnapshotStore(ctx.Viper) + if err != nil { + return err + } + snapshots, err := snapshotStore.List() + if err != nil { + return fmt.Errorf("failed to list snapshots: %w", err) + } + for _, snapshot := range snapshots { + cmd.Println("height:", snapshot.Height, "format:", snapshot.Format, "chunks:", snapshot.Chunks) + } + + return nil + }, +} diff --git a/client/snapshot/load.go b/client/snapshot/load.go new file mode 100644 index 000000000000..7834aa21e2e7 --- /dev/null +++ b/client/snapshot/load.go @@ -0,0 +1,113 @@ +package snapshot + +import ( + "archive/tar" + "bytes" + "compress/gzip" + "fmt" + "io" + "os" + "reflect" + "strconv" + + "github.com/cosmos/cosmos-sdk/server" + "github.com/spf13/cobra" + + snapshottypes "github.com/cosmos/cosmos-sdk/snapshots/types" +) + +const SnapshotFileName = "_snapshot" + +// LoadArchiveCmd load a portable archive format snapshot into snapshot store +func LoadArchiveCmd() *cobra.Command { + return &cobra.Command{ + Use: "load ", + Short: "Load a snapshot archive file (.tar.gz) into snapshot store", + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := server.GetServerContextFromCmd(cmd) + snapshotStore, err := server.GetSnapshotStore(ctx.Viper) + if err != nil { + return err + } + + path := args[0] + fp, err := os.Open(path) + if err != nil { + return fmt.Errorf("failed to open archive file: %w", err) + } + reader, err := gzip.NewReader(fp) + if err != nil { + return fmt.Errorf("failed to create gzip reader: %w", err) + } + + var snapshot snapshottypes.Snapshot + tr := tar.NewReader(reader) + if err != nil { + return fmt.Errorf("failed to create tar reader: %w", err) + } + + hdr, err := tr.Next() + if err != nil { + return fmt.Errorf("failed to read snapshot file header: %w", err) + } + if hdr.Name != SnapshotFileName { + return fmt.Errorf("invalid archive, expect file: snapshot, got: %s", hdr.Name) + } + bz, err := io.ReadAll(tr) + if err != nil { + return fmt.Errorf("failed to read snapshot file: %w", err) + } + if err := snapshot.Unmarshal(bz); err != nil { + return fmt.Errorf("failed to unmarshal snapshot: %w", err) + } + + // make sure the channel is unbuffered, because the tar reader can't do concurrency + chunks := make(chan io.ReadCloser) + quitChan := make(chan *snapshottypes.Snapshot) + go func() { + defer close(quitChan) + + savedSnapshot, err := snapshotStore.Save(snapshot.Height, snapshot.Format, chunks) + if err != nil { + cmd.Println("failed to save snapshot", err) + return + } + quitChan <- savedSnapshot + }() + + for i := uint32(0); i < snapshot.Chunks; i++ { + hdr, err = tr.Next() + if err != nil { + if err == io.EOF { + break + } + return err + } + + if hdr.Name != strconv.FormatInt(int64(i), 10) { + return fmt.Errorf("invalid archive, expect file: %d, got: %s", i, hdr.Name) + } + + bz, err := io.ReadAll(tr) + if err != nil { + return fmt.Errorf("failed to read chunk file: %w", err) + } + chunks <- io.NopCloser(bytes.NewReader(bz)) + } + close(chunks) + + savedSnapshot := <-quitChan + if savedSnapshot == nil { + return fmt.Errorf("failed to save snapshot") + } + + if !reflect.DeepEqual(&snapshot, savedSnapshot) { + _ = snapshotStore.Delete(snapshot.Height, snapshot.Format) + return fmt.Errorf("invalid archive, the saved snapshot is not equal to the original one") + } + + return nil + }, + } +} diff --git a/client/snapshot/restore.go b/client/snapshot/restore.go new file mode 100644 index 000000000000..7ab46dfe6b9e --- /dev/null +++ b/client/snapshot/restore.go @@ -0,0 +1,50 @@ +package snapshot + +import ( + "path/filepath" + "strconv" + + "github.com/spf13/cobra" + + "github.com/cosmos/cosmos-sdk/server" + servertypes "github.com/cosmos/cosmos-sdk/server/types" + dbm "github.com/tendermint/tm-db" +) + +// RestoreSnapshotCmd returns a command to restore a snapshot +func RestoreSnapshotCmd(appCreator servertypes.AppCreator) *cobra.Command { + cmd := &cobra.Command{ + Use: "restore ", + Short: "Restore app state from local snapshot", + Long: "Restore app state from local snapshot", + Args: cobra.ExactArgs(2), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := server.GetServerContextFromCmd(cmd) + + height, err := strconv.ParseUint(args[0], 10, 64) + if err != nil { + return err + } + format, err := strconv.ParseUint(args[1], 10, 32) + if err != nil { + return err + } + + home := ctx.Config.RootDir + db, err := openDB(home, server.GetAppDBBackend(ctx.Viper)) + if err != nil { + return err + } + app := appCreator(ctx.Logger, db, nil, ctx.Viper) + + sm := app.SnapshotManager() + return sm.RestoreLocalSnapshot(height, uint32(format)) + }, + } + return cmd +} + +func openDB(rootDir string, backendType dbm.BackendType) (dbm.DB, error) { + dataDir := filepath.Join(rootDir, "data") + return dbm.NewDB("application", backendType, dataDir) +} diff --git a/contrib/rosetta/rosetta-ci/data.tar.gz b/contrib/rosetta/rosetta-ci/data.tar.gz index 7ed3114345923c870cd7cc0b73a347088af7a4c6..ad152760a2e7a086ad8ec4404303001a738d710d 100644 GIT binary patch literal 47219 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

19z?H}%p=p6aQzxEHmedpotI-Tr4 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 diff --git a/docs/.vuepress/config.js b/docs/.vuepress/config.js index 57edfc9cc14c..5456c1eb95f8 100644 --- a/docs/.vuepress/config.js +++ b/docs/.vuepress/config.js @@ -30,10 +30,6 @@ module.exports = { index: "cosmos_network_vue" }, versions: [ - { - "label": "v0.44", - "key": "v0.44" - }, { "label": "v0.45", "key": "v0.45" @@ -42,6 +38,10 @@ module.exports = { "label": "v0.46", "key": "v0.46" }, + { + "label": "v0.47", + "key": "v0.47" + }, { "label": "main", "key": "main" diff --git a/docs/run-node/run-node.md b/docs/run-node/run-node.md index 2233f63aa128..19f2aa6bcf90 100644 --- a/docs/run-node/run-node.md +++ b/docs/run-node/run-node.md @@ -125,6 +125,43 @@ The previous command allow you to run a single node. This is enough for the next The naive way would be to run the same commands again in separate terminal windows. This is possible, however in the Cosmos SDK, we leverage the power of [Docker Compose](https://docs.docker.com/compose/) to run a localnet. If you need inspiration on how to set up your own localnet with Docker Compose, you can have a look at the Cosmos SDK's [`docker-compose.yml`](https://github.com/cosmos/cosmos-sdk/blob/v0.46.0-rc1/docker-compose.yml). -## Next {hide} +## State Sync -Read about the [Interacting with your Node](./interact-node.md) {hide} +State sync is the act in which a node syncs the latest or close to the latest state of a blockchain. This is useful for users who don't want to sync all the blocks in history. Read more in [CometBFT documentation](https://docs.cometbft.com/v0.34/core/state-sync). + +State sync works thanks to snapshots. Read how the SDK handles snapshots [here](https://github.com/cosmos/cosmos-sdk/blob/825245d/store/snapshots/README.md). + +### Local State Sync + +Local state sync work similar to normal state sync except that it works off a local snapshot of state instead of one provided via the p2p network. The steps to start local state sync are similar to normal state sync with a few different designs. + +1. As mentioned in https://docs.cometbft.com/v0.34/core/state-sync, one must set a height and hash in the config.toml along with a few rpc servers (the afromentioned link has instructions on how to do this). +2. Run ` ` to restore a local snapshot (note: first load it from a file with the *load* command). +3. Bootsrapping Comet state in order to start the node after the snapshot has been ingested. This can be done with the bootstrap command ` tendermint bootstrap-state` + +### Snapshots Commands + +The Cosmos SDK provides commands for managing snapshots. +These commands can be added in an app with the following snippet in `cmd//root.go`: + +```go +import ( + "github.com/cosmos/cosmos-sdk/client/snapshot" +) + +func initRootCmd(/* ... */) { + // ... + rootCmd.AddCommand( + snapshot.Cmd(appCreator), + ) +} +``` + +Then following commands are available at ` snapshots [command]`: + +* **list**: list local snapshots +* **load**: Load a snapshot archive file into snapshot store +* **restore**: Restore app state from local snapshot +* **export**: Export app state to snapshot store +* **dump**: Dump the snapshot as portable archive format +* **delete**: Delete a local snapshot diff --git a/go.mod b/go.mod index 5d0a8d78ee3f..3aaf3c199e8a 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ module github.com/cosmos/cosmos-sdk require ( cosmossdk.io/errors v1.0.0-beta.7 - cosmossdk.io/math v1.0.0-beta.3 + cosmossdk.io/math v1.0.0-rc.0 github.com/99designs/keyring v1.2.1 github.com/armon/go-metrics v0.4.1 github.com/bgentry/speakeasy v0.1.0 @@ -17,12 +17,12 @@ require ( github.com/cosmos/cosmos-proto v1.0.0-alpha7 github.com/cosmos/cosmos-sdk/db v1.0.0-beta.1 github.com/cosmos/go-bip39 v1.0.0 - github.com/cosmos/iavl v0.19.6-0.20230519111437-94ab9b2ae595 + github.com/cosmos/iavl v0.19.6 github.com/cosmos/ledger-cosmos-go v0.12.2 github.com/gogo/gateway v1.1.0 github.com/gogo/protobuf v1.3.2 github.com/golang/mock v1.6.0 - github.com/golang/protobuf v1.5.2 + github.com/golang/protobuf v1.5.3 github.com/google/uuid v1.3.0 github.com/gorilla/handlers v1.5.1 github.com/gorilla/mux v1.8.0 @@ -32,56 +32,56 @@ require ( github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d github.com/hdevalence/ed25519consensus v0.0.0-20220222234857-c00d1f31bab3 github.com/improbable-eng/grpc-web v0.15.0 - github.com/jhump/protoreflect v1.12.1-0.20220721211354-060cc04fc18b + github.com/jhump/protoreflect v1.15.1 github.com/magiconair/properties v1.8.6 github.com/manifoldco/promptui v0.9.0 - github.com/mattn/go-isatty v0.0.16 + github.com/mattn/go-isatty v0.0.18 github.com/pkg/errors v0.9.1 github.com/prometheus/client_golang v1.14.0 - github.com/prometheus/common v0.37.0 + github.com/prometheus/common v0.42.0 github.com/rakyll/statik v0.1.7 github.com/regen-network/cosmos-proto v0.3.1 - github.com/rs/zerolog v1.27.0 + github.com/rs/zerolog v1.29.1 github.com/spf13/cast v1.5.0 github.com/spf13/cobra v1.6.1 github.com/spf13/pflag v1.0.5 github.com/spf13/viper v1.13.0 - github.com/stretchr/testify v1.8.1 + github.com/stretchr/testify v1.8.2 github.com/tendermint/go-amino v0.16.0 - github.com/tendermint/tendermint v0.34.27 + github.com/tendermint/tendermint v0.34.28 github.com/tendermint/tm-db v0.6.7 github.com/tidwall/btree v1.5.0 - golang.org/x/crypto v0.5.0 - golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e - google.golang.org/genproto v0.0.0-20221118155620-16455021b5e6 - google.golang.org/grpc v1.52.0 - google.golang.org/protobuf v1.28.2-0.20220831092852-f930b1dc76e8 + golang.org/x/crypto v0.7.0 + golang.org/x/exp v0.0.0-20230310171629-522b1b587ee0 + google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4 + google.golang.org/grpc v1.54.0 + google.golang.org/protobuf v1.30.0 pgregory.net/rapid v0.4.7 sigs.k8s.io/yaml v1.3.0 ) require ( - cloud.google.com/go v0.105.0 // indirect - cloud.google.com/go/compute v1.12.1 // indirect - cloud.google.com/go/compute/metadata v0.2.1 // indirect - cloud.google.com/go/iam v0.7.0 // indirect - cloud.google.com/go/storage v1.27.0 // indirect + cloud.google.com/go v0.110.0 // indirect + cloud.google.com/go/compute v1.18.0 // indirect + cloud.google.com/go/compute/metadata v0.2.3 // indirect + cloud.google.com/go/iam v0.12.0 // indirect + cloud.google.com/go/storage v1.28.1 // indirect filippo.io/edwards25519 v1.0.0-rc.1 // indirect github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect - github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d // indirect + github.com/ChainSafe/go-schnorrkel v1.0.0 // indirect github.com/Workiva/go-datastructures v1.0.53 // indirect github.com/aws/aws-sdk-go v1.40.45 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect github.com/cenkalti/backoff/v4 v4.1.3 // indirect github.com/cespare/xxhash v1.1.0 // indirect - github.com/cespare/xxhash/v2 v2.1.2 // indirect + github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/cometbft/cometbft-db v0.7.0 // indirect github.com/cosmos/gorocksdb v1.2.0 // indirect github.com/creachadair/taskgroup v0.3.2 // indirect github.com/danieljoos/wincred v1.1.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 // indirect github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f // indirect github.com/dgraph-io/badger/v2 v2.2007.4 // indirect github.com/dgraph-io/ristretto v0.1.0 // indirect @@ -89,7 +89,7 @@ require ( github.com/dustin/go-humanize v1.0.0 // indirect github.com/dvsekhvalnov/jose2go v1.5.0 // indirect github.com/felixge/httpsnoop v1.0.1 // indirect - github.com/fsnotify/fsnotify v1.5.4 // indirect + github.com/fsnotify/fsnotify v1.6.0 // indirect github.com/go-kit/kit v0.12.0 // indirect github.com/go-kit/log v0.2.1 // indirect github.com/go-logfmt/logfmt v0.5.1 // indirect @@ -100,8 +100,8 @@ require ( github.com/google/btree v1.1.2 // indirect github.com/google/go-cmp v0.5.9 // indirect github.com/google/orderedcode v0.0.1 // indirect - github.com/googleapis/enterprise-certificate-proxy v0.2.0 // indirect - github.com/googleapis/gax-go/v2 v2.6.0 // indirect + github.com/googleapis/enterprise-certificate-proxy v0.2.3 // indirect + github.com/googleapis/gax-go/v2 v2.7.0 // indirect github.com/gorilla/websocket v1.5.0 // indirect github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c // indirect github.com/gtank/merlin v0.1.1 // indirect @@ -114,43 +114,45 @@ require ( github.com/inconshreveable/mousetrap v1.0.1 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/jmhodges/levigo v1.0.0 // indirect - github.com/klauspost/compress v1.15.11 // indirect - github.com/lib/pq v1.10.6 // indirect + github.com/klauspost/compress v1.16.0 // indirect + github.com/lib/pq v1.10.7 // indirect github.com/libp2p/go-buffer-pool v0.1.0 // indirect github.com/mattn/go-colorable v0.1.13 // indirect - github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect + github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect github.com/mimoo/StrobeGo v0.0.0-20210601165009-122bf33a46e0 // indirect github.com/minio/highwayhash v1.0.2 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect - github.com/mitchellh/go-testing-interface v1.0.0 // indirect + github.com/mitchellh/go-testing-interface v1.14.1 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/mtibben/percent v0.2.1 // indirect + github.com/onsi/gomega v1.20.0 // indirect github.com/pelletier/go-toml v1.9.5 // indirect - github.com/pelletier/go-toml/v2 v2.0.5 // indirect - github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 // indirect + github.com/pelletier/go-toml/v2 v2.0.7 // indirect + github.com/petermattis/goid v0.0.0-20230317030725-371a4b8eda08 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/client_model v0.3.0 // indirect - github.com/prometheus/procfs v0.8.0 // indirect + github.com/prometheus/procfs v0.9.0 // indirect github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect + github.com/rogpeppe/go-internal v1.9.0 // indirect github.com/rs/cors v1.8.2 // indirect github.com/sasha-s/go-deadlock v0.3.1 // indirect github.com/spf13/afero v1.8.2 // indirect github.com/spf13/jwalterweatherman v1.1.0 // indirect github.com/subosito/gotenv v1.4.1 // indirect - github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 // indirect + github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d // indirect github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c // indirect github.com/ulikunitz/xz v0.5.8 // indirect github.com/zondax/hid v0.9.1 // indirect github.com/zondax/ledger-go v0.14.1 // indirect go.etcd.io/bbolt v1.3.6 // indirect - go.opencensus.io v0.23.0 // indirect - golang.org/x/net v0.7.0 // indirect - golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783 // indirect - golang.org/x/sys v0.5.0 // indirect - golang.org/x/term v0.5.0 // indirect - golang.org/x/text v0.7.0 // indirect + go.opencensus.io v0.24.0 // indirect + golang.org/x/net v0.9.0 // indirect + golang.org/x/oauth2 v0.5.0 // indirect + golang.org/x/sys v0.7.0 // indirect + golang.org/x/term v0.7.0 // indirect + golang.org/x/text v0.9.0 // indirect golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect - google.golang.org/api v0.102.0 // indirect + google.golang.org/api v0.110.0 // indirect google.golang.org/appengine v1.6.7 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect @@ -164,16 +166,20 @@ replace ( // dgrijalva/jwt-go is deprecated and doesn't receive security updates. // TODO: remove it: https://github.com/cosmos/cosmos-sdk/issues/13134 github.com/dgrijalva/jwt-go => github.com/golang-jwt/jwt/v4 v4.4.2 - // Fix upstream GHSA-h395-qcrw-5vmq vulnerability. + // Fix upstream GHSA-h395-qcrw-5vmq and GHSA-3vp4-m3rf-835h vulnerabilities. // TODO Remove it: https://github.com/cosmos/cosmos-sdk/issues/10409 - github.com/gin-gonic/gin => github.com/gin-gonic/gin v1.7.0 + github.com/gin-gonic/gin => github.com/gin-gonic/gin v1.9.0 github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1 github.com/jhump/protoreflect => github.com/jhump/protoreflect v1.9.0 + // replace broken goleveldb. + github.com/syndtr/goleveldb => github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 // use cometbft - github.com/tendermint/tendermint => github.com/cometbft/cometbft v0.34.27 + github.com/tendermint/tendermint => github.com/cometbft/cometbft v0.34.28 ) retract ( + // revert fix https://github.com/cosmos/cosmos-sdk/pull/16331 + v0.46.12 // subject to a bug in the group module and gov module migration [v0.46.5, v0.46.6] // subject to the dragonberry vulnerability diff --git a/go.sum b/go.sum index e619e3e13c69..1035a8293d2f 100644 --- a/go.sum +++ b/go.sum @@ -19,8 +19,8 @@ cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHOb cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY= -cloud.google.com/go v0.105.0 h1:DNtEKRBAAzeS4KyIory52wWHuClNaXJ5x1F7xa4q+5Y= -cloud.google.com/go v0.105.0/go.mod h1:PrLgOJNe5nfE9UMxKxgXj4mD3voiP+YQ6gdt6KMFOKM= +cloud.google.com/go v0.110.0 h1:Zc8gqp3+a9/Eyph2KDmcGaPtbKRIoqq4YTlL4NMD0Ys= +cloud.google.com/go v0.110.0/go.mod h1:SJnCLqQ0FCFGSZMUNUf84MV3Aia54kn7pi8st7tMzaY= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= @@ -28,15 +28,15 @@ cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUM cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= cloud.google.com/go/bigtable v1.2.0/go.mod h1:JcVAOl45lrTmQfLj7T6TxyMzIN/3FGGcFm+2xVAli2o= -cloud.google.com/go/compute v1.12.1 h1:gKVJMEyqV5c/UnpzjjQbo3Rjvvqpr9B1DFSbJC4OXr0= -cloud.google.com/go/compute v1.12.1/go.mod h1:e8yNOBcBONZU1vJKCvCoDw/4JQsA0dpM4x/6PIIOocU= -cloud.google.com/go/compute/metadata v0.2.1 h1:efOwf5ymceDhK6PKMnnrTHP4pppY5L22mle96M1yP48= -cloud.google.com/go/compute/metadata v0.2.1/go.mod h1:jgHgmJd2RKBGzXqF5LR2EZMGxBkeanZ9wwa75XHJgOM= +cloud.google.com/go/compute v1.18.0 h1:FEigFqoDbys2cvFkZ9Fjq4gnHBP55anJ0yQyau2f9oY= +cloud.google.com/go/compute v1.18.0/go.mod h1:1X7yHxec2Ga+Ss6jPyjxRxpu2uu7PLgsOVXvgU0yacs= +cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= +cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= -cloud.google.com/go/iam v0.7.0 h1:k4MuwOsS7zGJJ+QfZ5vBK8SgHBAvYN/23BWsiihJ1vs= -cloud.google.com/go/iam v0.7.0/go.mod h1:H5Br8wRaDGNc8XP3keLc4unfUUZeyH3Sfl9XpQEYOeg= -cloud.google.com/go/longrunning v0.3.0 h1:NjljC+FYPV3uh5/OwWT6pVU+doBqMg2x/rZlE+CamDs= +cloud.google.com/go/iam v0.12.0 h1:DRtTY29b75ciH6Ov1PHb4/iat2CLCvrOm40Q0a6DFpE= +cloud.google.com/go/iam v0.12.0/go.mod h1:knyHGviacl11zrtZUoDuYpDgLjvr28sLQaG0YB2GYAY= +cloud.google.com/go/longrunning v0.4.1 h1:v+yFJOfKC3yZdY6ZUI933pIYdhyhV8S3NpWrXWmg7jM= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= @@ -47,13 +47,13 @@ cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohl cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= -cloud.google.com/go/storage v1.27.0 h1:YOO045NZI9RKfCj1c5A/ZtuuENUc8OAW+gHdGnDgyMQ= -cloud.google.com/go/storage v1.27.0/go.mod h1:x9DOL8TK/ygDUMieqwfhdpQryTeEkhGKMi80i/iqR2s= +cloud.google.com/go/storage v1.28.1 h1:F5QDG5ChchaAVQhINh24U99OWHURqrW8OmQcGKXcbgI= +cloud.google.com/go/storage v1.28.1/go.mod h1:Qnisd4CqDdo6BGs2AD5LLnEsmSQ80wQ5ogcBBKhU86Y= collectd.org v0.3.0/go.mod h1:A/8DzQBkF6abtvrT2j/AU/4tiBgJWYyh0y/oB/4MlWE= cosmossdk.io/errors v1.0.0-beta.7 h1:gypHW76pTQGVnHKo6QBkb4yFOJjC+sUGRc5Al3Odj1w= cosmossdk.io/errors v1.0.0-beta.7/go.mod h1:mz6FQMJRku4bY7aqS/Gwfcmr/ue91roMEKAmDUDpBfE= -cosmossdk.io/math v1.0.0-beta.3 h1:TbZxSopz2LqjJ7aXYfn7nJSb8vNaBklW6BLpcei1qwM= -cosmossdk.io/math v1.0.0-beta.3/go.mod h1:3LYasri3Zna4XpbrTNdKsWmD5fHHkaNAod/mNT9XdE4= +cosmossdk.io/math v1.0.0-rc.0 h1:ml46ukocrAAoBpYKMidF0R2tQJ1Uxfns0yH8wqgMAFc= +cosmossdk.io/math v1.0.0-rc.0/go.mod h1:Ygz4wBHrgc7g0N+8+MrnTfS9LLn9aaTGa9hKopuym5k= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= filippo.io/edwards25519 v1.0.0-rc.1 h1:m0VOOB23frXZvAOK44usCgLWvtsxIoMCTBGJZlpmGfU= filippo.io/edwards25519 v1.0.0-rc.1/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns= @@ -67,8 +67,8 @@ github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v0.3.0/go.mod h1:tPaiy8S5bQ github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d h1:nalkkPQcITbvhmL4+C4cKA87NW0tfm3Kl9VXRoPywFg= -github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d/go.mod h1:URdX5+vg25ts3aCh8H5IFZybJYKWhJHYMTnf+ULtoC4= +github.com/ChainSafe/go-schnorrkel v1.0.0 h1:3aDA67lAykLaG1y3AOjs88dMxC88PgUuHRrLeDnvGIM= +github.com/ChainSafe/go-schnorrkel v1.0.0/go.mod h1:dpzHYVxLZcp8pjlV+O+UR8K0Hp/z7vcchBSbMBEhCw4= github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/DataDog/zstd v1.5.0/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= @@ -158,6 +158,9 @@ github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= github.com/bwesterb/go-ristretto v1.2.0/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0= +github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM= +github.com/bytedance/sonic v1.8.0 h1:ea0Xadu+sHlu7x5O3gKhRpQ1IKiMrSiHttPF0ybECuA= +github.com/bytedance/sonic v1.8.0/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U= github.com/c-bata/go-prompt v0.2.2/go.mod h1:VzqtzE2ksDBcdln8G7mk2RX9QyGjH+OVqOCSiVIqS34= github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4= @@ -170,9 +173,12 @@ github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= -github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cheggaaa/pb v1.0.27/go.mod h1:pQciLPpbU0oxA0h+VJYYLxO+XeDQb5pZijXscXHm81s= +github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY= +github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 h1:qSGYFH7+jGhDF8vLC+iwCD4WpbV1EBDSzWkJODFLams= +github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk= github.com/chzyer/logex v1.1.10 h1:Swpa1K6QvQznwJRcfTfQJmTE72DqScAa40E+fbHEXEE= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e h1:fY5BOSpyZCqRo5OhCuC+XN+r/bBCmeuuJtjz+bCNIf8= @@ -194,8 +200,8 @@ github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE github.com/coinbase/kryptology v1.8.0/go.mod h1:RYXOAPdzOGUe3qlSFkMGn58i3xUA8hmxYHksuq+8ciI= github.com/coinbase/rosetta-sdk-go v0.7.9 h1:lqllBjMnazTjIqYrOGv8h8jxjg9+hJazIGZr9ZvoCcA= github.com/coinbase/rosetta-sdk-go v0.7.9/go.mod h1:0/knutI7XGVqXmmH4OQD8OckFrbQ8yMsUZTG7FXCR2M= -github.com/cometbft/cometbft v0.34.27 h1:ri6BvmwjWR0gurYjywcBqRe4bbwc3QVs9KRcCzgh/J0= -github.com/cometbft/cometbft v0.34.27/go.mod h1:BcCbhKv7ieM0KEddnYXvQZR+pZykTKReJJYf7YC7qhw= +github.com/cometbft/cometbft v0.34.28 h1:gwryf55P1SWMUP4nOXpRVI2D0yPoYEzN+IBqmRBOsDc= +github.com/cometbft/cometbft v0.34.28/go.mod h1:L9shMfbkZ8B+7JlwANEr+NZbBcn+hBpwdbeYvA5rLCw= github.com/cometbft/cometbft-db v0.7.0 h1:uBjbrBx4QzU0zOEnU8KxoDl18dMNgDh+zZRUE0ucsbo= github.com/cometbft/cometbft-db v0.7.0/go.mod h1:yiKJIm2WKrt6x8Cyxtq9YTEcIMPcEe4XPxhgX59Fzf0= github.com/confio/ics23/go v0.9.0 h1:cWs+wdbS2KRPZezoaaj+qBleXgUk5WOQFMP3CQFGTr4= @@ -209,7 +215,7 @@ github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/go-systemd/v22 v22.3.3-0.20220203105225-a9a7ef127534/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cosmos/btcutil v1.0.5 h1:t+ZFcX77LpKtDBhjucvnOH8C2l2ioGsBNEQ3jef8xFk= github.com/cosmos/btcutil v1.0.5/go.mod h1:IyB7iuqZMJlthe2tkIFL33xPyzbFYP0XVdS8P5lUPis= @@ -222,8 +228,8 @@ github.com/cosmos/go-bip39 v1.0.0 h1:pcomnQdrdH22njcAatO0yWojsUnCO3y2tNoV1cb6hHY github.com/cosmos/go-bip39 v1.0.0/go.mod h1:RNJv0H/pOIVgxw6KS7QeX2a0Uo0aKUlfhZ4xuwvCdJw= github.com/cosmos/gorocksdb v1.2.0 h1:d0l3jJG8M4hBouIZq0mDUHZ+zjOx044J3nGRskwTb4Y= github.com/cosmos/gorocksdb v1.2.0/go.mod h1:aaKvKItm514hKfNJpUJXnnOWeBnk2GL4+Qw9NHizILw= -github.com/cosmos/iavl v0.19.6-0.20230519111437-94ab9b2ae595 h1:4le4qBywHO2/1TmnLnSTw2zLsgjHCwgmWsJNo/iQTi4= -github.com/cosmos/iavl v0.19.6-0.20230519111437-94ab9b2ae595/go.mod h1:X9PKD3J0iFxdmgNLa7b2LYWdsGd90ToV5cAONApkEPw= +github.com/cosmos/iavl v0.19.6 h1:XY78yEeNPrEYyNCKlqr9chrwoeSDJ0bV2VjocTk//OU= +github.com/cosmos/iavl v0.19.6/go.mod h1:X9PKD3J0iFxdmgNLa7b2LYWdsGd90ToV5cAONApkEPw= github.com/cosmos/keyring v1.2.0 h1:8C1lBP9xhImmIabyXW4c3vFjjLiBdGCmfLUfeZlV1Yo= github.com/cosmos/keyring v1.2.0/go.mod h1:fc+wB5KTk9wQ9sDx0kFXB3A0MaeGHM9AwRStKOQ5vOA= github.com/cosmos/ledger-cosmos-go v0.12.2 h1:/XYaBlE2BJxtvpkHiBm97gFGSGmYGKunKyF3nNqAXZA= @@ -246,8 +252,9 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/deckarep/golang-set v1.8.0/go.mod h1:5nI87KwE7wgsBU1F4GKAw2Qod7p5kyS383rP6+o6qqo= github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0= github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= -github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1m5sE92cU+pd5Mcc= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 h1:HbphB4TFFXpv7MNrT52FGrrgVXF1owhMVTHFZIlnvd4= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0/go.mod h1:DZGJHZMqrU4JJqFAWUS2UO1+lbSKsdiOoYi9Zzey7Fc= github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= github.com/deepmap/oapi-codegen v1.6.0/go.mod h1:ryDa9AgbELGeB+YEXE1dR53yAjHwFvE9iAUlWl9Al3M= github.com/deepmap/oapi-codegen v1.8.2/go.mod h1:YLgSKSDv/bZQB7N4ws6luhozi3cEdRktEqrX88CvjIw= @@ -305,16 +312,16 @@ github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2 github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI= -github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= +github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= +github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= github.com/getkin/kin-openapi v0.53.0/go.mod h1:7Yn5whZr5kJi6t+kShccXS8ae1APpYTW6yheSwk8Yi4= github.com/getkin/kin-openapi v0.61.0/go.mod h1:7Yn5whZr5kJi6t+kShccXS8ae1APpYTW6yheSwk8Yi4= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= -github.com/gin-gonic/gin v1.7.0 h1:jGB9xAJQ12AIGNB4HguylppmDK1Am9ppF7XnGXXJuoU= -github.com/gin-gonic/gin v1.7.0/go.mod h1:jD2toBW3GZUr5UMcdrwQA10I7RuaFOl/SGeDjXkfUtY= +github.com/gin-gonic/gin v1.9.0 h1:OjyFBKICoexlu99ctXNR2gg+c5pKrKMuyjgARg9qeY8= +github.com/gin-gonic/gin v1.9.0/go.mod h1:W1Me9+hsUSyj3CePGrd1/QrKJMSJ1Tu/0hFEH89961k= github.com/glycerine/go-unsnap-stream v0.0.0-20180323001048-9f0cb55181dd/go.mod h1:/20jfyN9Y5QPEAprSgKAUr+glWDY39ZiUEAYOEv5dsE= github.com/glycerine/goconvey v0.0.0-20190410193231-58a59202ab31/go.mod h1:Ogl1Tioa0aV7gstGFO7KhffUsb9M4ydbEbbxpcEDc24= github.com/go-chi/chi/v5 v5.0.0/go.mod h1:BBug9lr0cqtdAhsu6R4AAdvufI0/XBzAQSsUqJpoZOs= @@ -326,8 +333,6 @@ github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2 github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o= github.com/go-kit/kit v0.12.0 h1:e4o3o3IsBfAKQh5Qbbiqyfu97Ku7jrO/JbohvztANh4= github.com/go-kit/kit v0.12.0/go.mod h1:lHd+EkCZPIwYItmGDDRdhinkzX2A1sj+M9biaEaizzs= -github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= -github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= github.com/go-kit/log v0.2.1 h1:MRVx0/zhvdseW+Gza6N9rVzU/IVzaeE1SFI4raAhmBU= github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= @@ -338,13 +343,13 @@ github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KE github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= -github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= -github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q= -github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= -github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no= -github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= -github.com/go-playground/validator/v10 v10.4.1 h1:pH2c5ADXtd66mxoE0Zm9SUhxE20r7aM3F26W0hOn+GE= -github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4= +github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= +github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= +github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= +github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= +github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= +github.com/go-playground/validator/v10 v10.11.2 h1:q3SHpufmypg+erIExEKUmsgmhDTyhcJ38oeKGACXohU= +github.com/go-playground/validator/v10 v10.11.2/go.mod h1:NieE624vt4SCTJtD87arVLvdmjPAeV8BQlHtMnw9D7s= github.com/go-sourcemap/sourcemap v2.1.3+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= @@ -355,6 +360,8 @@ github.com/gobwas/pool v0.2.0 h1:QEmUOlnSjWtnpRGHF3SauEiOsy82Cup83Vf2LcMlnc8= github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= github.com/gobwas/ws v1.0.2 h1:CoAavW/wd/kulfZmSIBt6p24n4j7tHgNVCjsfHVNUbo= github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM= +github.com/goccy/go-json v0.10.0 h1:mXKd9Qw4NuzShiRlOXKews24ufknHO7gx30lsDyokKA= +github.com/goccy/go-json v0.10.0/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 h1:ZpnhV/YsD2/4cESfV5+Hoeu/iUR3ruzNvZ+yQfO03a0= github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= @@ -400,8 +407,8 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= -github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= @@ -434,7 +441,7 @@ github.com/google/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPg github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/martian/v3 v3.2.1 h1:d8MncMlErDFTwQGBK1xhv026j9kqhvw1Qv9IbWT1VLQ= +github.com/google/martian/v3 v3.3.2 h1:IqNFLAmvJOgVlpdEBiQbDc2EwKW77amAycfTuWKdfvw= github.com/google/orderedcode v0.0.1 h1:UzfcAexk9Vhv8+9pNOgRu41f16lHq725vPwnSeiG/Us= github.com/google/orderedcode v0.0.1/go.mod h1:iVyU4/qPKHY5h/wSd6rZZCDcLJNxiWO6dvsYES2Sb20= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= @@ -454,12 +461,12 @@ github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+ github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/enterprise-certificate-proxy v0.2.0 h1:y8Yozv7SZtlU//QXbezB6QkpuE6jMD2/gfzk4AftXjs= -github.com/googleapis/enterprise-certificate-proxy v0.2.0/go.mod h1:8C0jb7/mgJe/9KK8Lm7X9ctZC2t60YyIpYEI16jx0Qg= +github.com/googleapis/enterprise-certificate-proxy v0.2.3 h1:yk9/cqRKtT9wXZSsRH9aurXEpJX+U6FLtpYTdC3R06k= +github.com/googleapis/enterprise-certificate-proxy v0.2.3/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/googleapis/gax-go/v2 v2.6.0 h1:SXk3ABtQYDT/OH8jAyvEOQ58mgawq5C4o/4/89qN2ZU= -github.com/googleapis/gax-go/v2 v2.6.0/go.mod h1:1mjbznJAPHFpesgE5ucqfYEscaz5kMdcIDwU/6+DDoY= +github.com/googleapis/gax-go/v2 v2.7.0 h1:IcsPKeInNvYi7eqSaDjiZqDDKu5rsmunY0Y1YupQSSQ= +github.com/googleapis/gax-go/v2 v2.7.0/go.mod h1:TEop28CZZQ2y+c0VxMUmu1lV+fQx57QpBWsYpwqHJx8= github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gordonklaus/ineffassign v0.0.0-20200309095847-7953dde2c7bf/go.mod h1:cuNKsD1zp2v6XfE/orVX2QE1LC+i254ceGcVeDT3pTU= @@ -580,7 +587,6 @@ github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/u github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= @@ -600,9 +606,12 @@ github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYs github.com/klauspost/compress v1.11.2/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.11.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= -github.com/klauspost/compress v1.15.11 h1:Lcadnb3RKGin4FYM/orgq0qde+nc15E5Cbqg4B9Sx9c= -github.com/klauspost/compress v1.15.11/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM= +github.com/klauspost/compress v1.16.0 h1:iULayQNOReoYUe+1qtKOqw9CwJv3aNQu8ivo7lw1HU4= +github.com/klauspost/compress v1.16.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/klauspost/cpuid v0.0.0-20170728055534-ae7887de9fa5 h1:2U0HzY8BJ8hVwDKIzp7y4voR9CX/nvcfymLmg2UiOio= github.com/klauspost/cpuid v0.0.0-20170728055534-ae7887de9fa5/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= +github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4= +github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/crc32 v0.0.0-20161016154125-cb6bfca970f6/go.mod h1:+ZoRqAPRLkC4NPOvfYeR5KNOrY6TD+/sAC3HXPZgDYg= github.com/klauspost/pgzip v1.0.2-0.20170402124221-0bf5dcad4ada/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= @@ -611,7 +620,8 @@ github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= @@ -620,11 +630,11 @@ github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+ github.com/labstack/echo/v4 v4.2.1/go.mod h1:AA49e0DZ8kk5jTOOCKNuPR6oTnBS0dYiM4FW1e6jwpg= github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k= github.com/leanovate/gopter v0.2.9/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8= -github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y= -github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= +github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w= +github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY= github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= -github.com/lib/pq v1.10.6 h1:jbk+ZieJ0D7EVGJYpL9QTz7/YW6UHbmdnZWYyK5cdBs= -github.com/lib/pq v1.10.6/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/lib/pq v1.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw= +github.com/lib/pq v1.10.7/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6cdF0Y8= github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg= github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= @@ -653,8 +663,10 @@ github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hd github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= -github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.18 h1:DOKFKCQ7FNG2L1rbrmstDN4QVRdS89Nkh85u68Uwp98= +github.com/mattn/go-isatty v0.0.18/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= @@ -662,8 +674,8 @@ github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m github.com/mattn/go-sqlite3 v1.11.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= github.com/mattn/go-tty v0.0.0-20180907095812-13ff1204f104/go.mod h1:XPvLUNfbS4fJH25nqRHfWLMa1ONC8Amw+mIA639KxkE= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 h1:I0XW9+e1XWDxdcEniV4rQAIOPUGDq67JSCiRCgGCZLI= -github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= +github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= +github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/mimoo/StrobeGo v0.0.0-20181016162300-f8f6d4d2b643/go.mod h1:43+3pMjjKimDBf5Kr4ZFNGbLql1zKkbImw+fZbw3geM= github.com/mimoo/StrobeGo v0.0.0-20210601165009-122bf33a46e0 h1:QRUSJEgZn2Snx0EmT/QLXibWjSUDjKWvXIT19NBVp94= @@ -674,8 +686,9 @@ github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceT github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/go-testing-interface v1.0.0 h1:fzU/JVNcaqHQEcVFAKeR41fkiLdIPrefOvVG1VZ96U0= github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= +github.com/mitchellh/go-testing-interface v1.14.1 h1:jrgshOhYAUVNMAJiKbEu7EqAwgJJ2JqpQmpLJOu07cU= +github.com/mitchellh/go-testing-interface v1.14.1/go.mod h1:gfgS7OtZj6MA4U1UrDRp04twqAjfvlZyCfX3sDjEym8= github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= @@ -727,8 +740,9 @@ github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9k github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= -github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/onsi/gomega v1.20.0 h1:8W0cWlwFkflGPLltQvLRB7ZVD5HuP6ng320w2IS245Q= +github.com/onsi/gomega v1.20.0/go.mod h1:DtrZpjmvpn2mPm4YWQa0/ALMDj9v4YxLgojwPeREyVo= github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/image-spec v1.1.0-rc2 h1:2zx/Stx4Wc5pIPDvIxHXvXtQFW/7XWJGmnM7r3wg034= @@ -752,17 +766,20 @@ github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtP github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= -github.com/pelletier/go-toml/v2 v2.0.5 h1:ipoSadvV8oGUjnUbMub59IDPPwfxF694nG/jwbMiyQg= -github.com/pelletier/go-toml/v2 v2.0.5/go.mod h1:OMHamSCAODeSsVrwwvcJOaoN0LIUIaFVNZzmWyNfXas= +github.com/pelletier/go-toml/v2 v2.0.6/go.mod h1:eumQOmlWiOPt5WriQQqoM5y18pDHwha2N+QD+EUNTek= +github.com/pelletier/go-toml/v2 v2.0.7 h1:muncTPStnKRos5dpVKULv2FVd4bMOhNePj9CjgDb8Us= +github.com/pelletier/go-toml/v2 v2.0.7/go.mod h1:eumQOmlWiOPt5WriQQqoM5y18pDHwha2N+QD+EUNTek= github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= github.com/peterh/liner v1.0.1-0.20180619022028-8c1271fcf47f/go.mod h1:xIteQHvHuaLYG9IFj6mSxM0fCKrs34IrEQUhOYuGPHc= github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7/go.mod h1:CRroGNssyjTd/qIG2FyxByd2S8JEAZXBl4qUrZf8GS0= -github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 h1:q2e307iGHPdTGp0hoxKjt1H5pDo6utceo3dQVK3I5XQ= github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5/go.mod h1:jvVRKCrJTQWu0XVbaOlby/2lO20uSCHEMzzplHXte1o= +github.com/petermattis/goid v0.0.0-20230317030725-371a4b8eda08 h1:hDSdbBuw3Lefr6R18ax0tZ2BJeNB3NehB3trOwYBsdU= +github.com/petermattis/goid v0.0.0-20230317030725-371a4b8eda08/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4= github.com/philhofer/fwd v1.0.0/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU= github.com/philhofer/fwd v1.1.1/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU= github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= @@ -779,8 +796,6 @@ github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5Fsn github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= -github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= -github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= github.com/prometheus/client_golang v1.14.0 h1:nJdhIvne2eSX/XRAFV9PcvFFRbrjbcTUj0VP62TMhnw= github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQgYNtG/XQE4E/Zae36Y= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= @@ -799,20 +814,16 @@ github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt2 github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/common v0.15.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= -github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= -github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= -github.com/prometheus/common v0.37.0 h1:ccBbHCgIiT9uSoFY0vX8H3zsNR5eLt17/RQLUvn8pXE= -github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA= +github.com/prometheus/common v0.42.0 h1:EKsfXEYo4JpWMHH5cg+KOUWeuJSov1Id8zGR8eeI1YM= +github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.3.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo= -github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4= +github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJfhI= +github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/rakyll/statik v0.1.7 h1:OF3QCZUuyPxuGEP7B4ypUa7sB/iHtqOTDYZXGM8KOdQ= github.com/rakyll/statik v0.1.7/go.mod h1:AlZONWzMtEnMs7W4e/1LURLiI49pIMmp6V9Unghqrcc= @@ -828,13 +839,16 @@ github.com/rjeczalik/notify v0.9.1/go.mod h1:rKwnCoCGeuQnwBtTSPL9Dad03Vh2n40ePRr github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k= +github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= +github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= +github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/rs/cors v1.8.2 h1:KCooALfAYGs415Cwu5ABvv9n9509fSiG5SQJn/AQo4U= github.com/rs/cors v1.8.2/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= -github.com/rs/xid v1.3.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= -github.com/rs/zerolog v1.27.0 h1:1T7qCieN22GVc8S4Q2yuexzBb1EqjbgjSH9RohbMjKs= -github.com/rs/zerolog v1.27.0/go.mod h1:7frBqO0oezxmnO7GF86FY++uy8I0Tk/If5ni1G9Qc0U= +github.com/rs/xid v1.4.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= +github.com/rs/zerolog v1.29.1 h1:cO+d60CHkknCbvzEWxP0S9K6KqyTjrCNUy1LdQLCGPc= +github.com/rs/zerolog v1.29.1/go.mod h1:Le6ESbR7hc+DP6Lt1THiV8CQSdkkNrd3R0XbEgp3ZBU= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= @@ -899,8 +913,9 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= +github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/subosito/gotenv v1.4.1 h1:jyEFiXpy21Wm81FBN71l9VoMMV8H8jG+qIK3GCpY6Qs= github.com/subosito/gotenv v1.4.1/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= @@ -925,13 +940,13 @@ github.com/tklauser/numcpus v0.2.2/go.mod h1:x3qojaO3uyYt0i56EW/VUYs7uBvdl2fkfZF github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/ttacon/chalk v0.0.0-20160626202418-22c06c80ed31/go.mod h1:onvgF043R+lC5RZ8IT9rBXDaEDnpnw/Cl+HFiw+v/7Q= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= +github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= +github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs= github.com/tyler-smith/go-bip39 v1.0.2/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs= -github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo= -github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= -github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs= -github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= +github.com/ugorji/go/codec v1.2.9 h1:rmenucSohSTiyL09Y+l2OCk+FrMxGMzho2+tjr5ticU= +github.com/ugorji/go/codec v1.2.9/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= github.com/ulikunitz/xz v0.5.8 h1:ERv8V6GKqVi23rgu5cj9pVfVzJbOqAY2Ntl88O6c2nQ= github.com/ulikunitz/xz v0.5.8/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= @@ -952,6 +967,7 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/zondax/hid v0.9.1 h1:gQe66rtmyZ8VeGFcOpbuH3r7erYtNEAezCAYu8LdkJo= github.com/zondax/hid v0.9.1/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM= github.com/zondax/ledger-go v0.14.1 h1:Pip65OOl4iJ84WTpA4BKChvOufMhhbxED3BaihoZN4c= @@ -968,8 +984,8 @@ go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= -go.opencensus.io v0.23.0 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M= -go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= +go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= +go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= @@ -979,6 +995,8 @@ go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9E go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= +golang.org/x/arch v0.0.0-20210923205945-b76863e36670 h1:18EFjUmQOcUvxNYSkA6jO9VAiXCnxFY6NyDX0bHDmkU= +golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= @@ -1000,9 +1018,11 @@ golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWP golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.5.0 h1:U/0M97KRkSFvyD/3FSmdP5W5swImpNgle/EHFhOsQPE= golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU= +golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A= +golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -1017,8 +1037,8 @@ golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= golang.org/x/exp v0.0.0-20200331195152-e8c3332aa8e5/go.mod h1:4M0jN8W1tt0AVLNr8HDosyJCDCDuyL9N9+3m7wDWgKw= -golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e h1:+WEEuIdZHnUeJJmEUjyYC2gfUMj69yZXw17EnHg/otA= -golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e/go.mod h1:Kr81I6Kryrl9sr8s2FK3vxD90NdsKWRuOIl2O4CvYbA= +golang.org/x/exp v0.0.0-20230310171629-522b1b587ee0 h1:LGJsf5LRplCck6jUCH3dBL2dmycNruWNF5xugkSlfXw= +golang.org/x/exp v0.0.0-20230310171629-522b1b587ee0/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= @@ -1044,7 +1064,8 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.7.0 h1:LapD9S96VoQRhi/GrNTqeBJFrUjs5UHCAtTlgwA5oZA= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.8.0 h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1093,15 +1114,15 @@ golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20210220033124-5f55cee0dc0d/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210610132358-84b48f89b13b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM= +golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -1111,10 +1132,8 @@ golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= -golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783 h1:nt+Q6cXKz4MosCSpnbMtqiQ8Oz0pxTef2B4Vca2lvfk= -golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= +golang.org/x/oauth2 v0.5.0 h1:HuArIo48skDwlrvM3sEdHXElYslAMsf3KwRkkW4MC4s= +golang.org/x/oauth2 v0.5.0/go.mod h1:9/XBHVqLaWO3/BRHs5jbpYCnOZVjj5V0ndyaAM7KB4I= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1126,6 +1145,7 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1195,7 +1215,6 @@ golang.org/x/sys v0.0.0-20210420205809-ac73e9fd8988/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -1203,18 +1222,23 @@ golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210819135213-f52c844e1c1c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220517195934-5e4e11fc645e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= +golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU= +golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.5.0 h1:n2a8QNdAb0sZNpU9R1ALUXBbY+w51fCQDN+7EdxNBsY= +golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.7.0 h1:BEvjmm5fURWqcfbSKTdpkDXYBrUS1c0m8agp14W48vQ= +golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1224,8 +1248,11 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo= +golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= +golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -1294,7 +1321,8 @@ golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.4.0 h1:7mTAgkunk3fr4GAloyyCasadO6h9zSsQZbwvcaIciV4= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -1327,8 +1355,8 @@ google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz513 google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= -google.golang.org/api v0.102.0 h1:JxJl2qQ85fRMPNvlZY/enexbxpCjLwGhZUtgfGeQ51I= -google.golang.org/api v0.102.0/go.mod h1:3VFl6/fzoA+qNuS1N1/VfXY4LjoXN/wzeIp7TweWwGo= +google.golang.org/api v0.110.0 h1:l+rh0KYUooe9JGbGVx71tbFo4SMbMTXK3I3ia2QSEeU= +google.golang.org/api v0.110.0/go.mod h1:7FC4Vvx1Mooxh8C5HWjzZHcavuS2f6pmJpZx60ca7iI= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -1382,8 +1410,8 @@ google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210126160654-44e461bb6506/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20221118155620-16455021b5e6 h1:a2S6M0+660BgMNl++4JPlcAO/CjkqYItDEZwkoDQK7c= -google.golang.org/genproto v0.0.0-20221118155620-16455021b5e6/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= +google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4 h1:DdoeryqhaXp1LtT/emMP1BRJPHHKFi5akj/nbx/zNTA= +google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4/go.mod h1:NWraEVixdDnqcqQ30jipen1STv2r/n24Wb7twVTGR4s= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.19.1/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= @@ -1408,8 +1436,8 @@ google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTp google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.52.0 h1:kd48UiU7EHsV4rnLyOJRuP/Il/UHE7gdDAQ+SZI7nZk= -google.golang.org/grpc v1.52.0/go.mod h1:pu6fVzoFb+NBYNAvQL08ic+lvB2IojljRYuun5vorUY= +google.golang.org/grpc v1.54.0 h1:EhTqbhiYeixwWQtAEZAxmV9MGqcjEU2mFx52xCzNyag= +google.golang.org/grpc v1.54.0/go.mod h1:PUSEXI6iWghWaB6lXM4knEgpJNu2qUcKfDtNci3EC2g= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -1424,8 +1452,9 @@ google.golang.org/protobuf v1.25.1-0.20200805231151-a709e31e5d12/go.mod h1:9JNX7 google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.28.2-0.20220831092852-f930b1dc76e8 h1:KR8+MyP7/qOlV+8Af01LtjL04bu7on42eVsxT4EyBQk= -google.golang.org/protobuf v1.28.2-0.20220831092852-f930b1dc76e8/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= +google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/proto/cosmos/group/v1/events.proto b/proto/cosmos/group/v1/events.proto index c2cfe8728f72..2b98ec9abc32 100644 --- a/proto/cosmos/group/v1/events.proto +++ b/proto/cosmos/group/v1/events.proto @@ -79,3 +79,16 @@ message EventLeaveGroup { // address is the account address of the group member. string address = 2 [(cosmos_proto.scalar) = "cosmos.AddressString"]; } + +// EventProposalPruned is an event emitted when a proposal is pruned. +message EventProposalPruned { + + // proposal_id is the unique ID of the proposal. + uint64 proposal_id = 1; + + // status is the proposal status (UNSPECIFIED, SUBMITTED, ACCEPTED, REJECTED, ABORTED, WITHDRAWN). + ProposalStatus status = 2; + + // tally_result is the proposal tally result (when applicable). + TallyResult tally_result = 3; +} diff --git a/proto/cosmos/group/v1/query.proto b/proto/cosmos/group/v1/query.proto index 51a011a9db8f..20516d327702 100644 --- a/proto/cosmos/group/v1/query.proto +++ b/proto/cosmos/group/v1/query.proto @@ -82,6 +82,13 @@ service Query { rpc TallyResult(QueryTallyResultRequest) returns (QueryTallyResultResponse) { option (google.api.http).get = "/cosmos/group/v1/proposals/{proposal_id}/tally"; }; + + // Groups queries all groups in state. + // + // Since: cosmos-sdk 0.47.1 + rpc Groups(QueryGroupsRequest) returns (QueryGroupsResponse) { + option (google.api.http).get = "/cosmos/group/v1/groups"; + }; } // QueryGroupInfoRequest is the Query/GroupInfo request type. @@ -311,3 +318,23 @@ message QueryTallyResultResponse { // tally defines the requested tally. TallyResult tally = 1 [(gogoproto.nullable) = false]; } + +// QueryGroupsRequest is the Query/Groups request type. +// +// Since: cosmos-sdk 0.47.1 +message QueryGroupsRequest { + + // pagination defines an optional pagination for the request. + cosmos.base.query.v1beta1.PageRequest pagination = 2; +} + +// QueryGroupsResponse is the Query/Groups response type. +// +// Since: cosmos-sdk 0.47.1 +message QueryGroupsResponse { + // `groups` is all the groups present in state. + repeated GroupInfo groups = 1; + + // pagination defines the pagination in the response. + cosmos.base.query.v1beta1.PageResponse pagination = 2; +} diff --git a/proto/cosmos/group/v1/types.proto b/proto/cosmos/group/v1/types.proto index 837271542c63..d975d6b62da6 100644 --- a/proto/cosmos/group/v1/types.proto +++ b/proto/cosmos/group/v1/types.proto @@ -14,7 +14,6 @@ import "google/protobuf/any.proto"; // Member represents a group member with an account address, // non-zero weight, metadata and added_at timestamp. message Member { - // address is the member's account address. string address = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"]; @@ -32,7 +31,6 @@ message Member { // Contrary to `Member`, it doesn't have any `added_at` field // since this field cannot be set as part of requests. message MemberRequest { - // address is the member's account address. string address = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"]; @@ -120,7 +118,6 @@ enum VoteOption { // GroupInfo represents the high-level on-chain information for a group. message GroupInfo { - // id is the unique ID of the group. uint64 id = 1; @@ -145,7 +142,6 @@ message GroupInfo { // GroupMember represents the relationship between a group and a member. message GroupMember { - // group_id is the unique ID of the group. uint64 group_id = 1; @@ -299,7 +295,6 @@ message TallyResult { // Vote represents a vote for a proposal. message Vote { - // proposal is the unique ID of the proposal. uint64 proposal_id = 1; diff --git a/proto/cosmos/vesting/v1beta1/tx.proto b/proto/cosmos/vesting/v1beta1/tx.proto index 27511ba80cbd..732fe12536b2 100644 --- a/proto/cosmos/vesting/v1beta1/tx.proto +++ b/proto/cosmos/vesting/v1beta1/tx.proto @@ -39,6 +39,7 @@ message MsgCreateVestingAccount { repeated cosmos.base.v1beta1.Coin amount = 3 [(gogoproto.nullable) = false, (gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins"]; + // end of vesting as unix time (in seconds). int64 end_time = 4; bool delayed = 5; } @@ -75,6 +76,7 @@ message MsgCreatePeriodicVestingAccount { string from_address = 1; string to_address = 2; + // start of vesting as unix time (in seconds). int64 start_time = 3; repeated Period vesting_periods = 4 [(gogoproto.nullable) = false]; } diff --git a/proto/cosmos/vesting/v1beta1/vesting.proto b/proto/cosmos/vesting/v1beta1/vesting.proto index 824cc30d8bb1..d5c1c9e583d7 100644 --- a/proto/cosmos/vesting/v1beta1/vesting.proto +++ b/proto/cosmos/vesting/v1beta1/vesting.proto @@ -20,6 +20,7 @@ message BaseVestingAccount { [(gogoproto.nullable) = false, (gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins"]; repeated cosmos.base.v1beta1.Coin delegated_vesting = 4 [(gogoproto.nullable) = false, (gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins"]; + // Vesting end time, as unix timestamp (in seconds). int64 end_time = 5; } @@ -30,6 +31,7 @@ message ContinuousVestingAccount { option (gogoproto.goproto_stringer) = false; BaseVestingAccount base_vesting_account = 1 [(gogoproto.embed) = true]; + // Vesting start time, as unix timestamp (in seconds). int64 start_time = 2; } @@ -47,6 +49,7 @@ message DelayedVestingAccount { message Period { option (gogoproto.goproto_stringer) = false; + // Period duration in seconds. int64 length = 1; repeated cosmos.base.v1beta1.Coin amount = 2 [(gogoproto.nullable) = false, (gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins"]; diff --git a/scripts/protocgen.sh b/scripts/protocgen.sh index 3e740c8b630a..636479f79ac5 100755 --- a/scripts/protocgen.sh +++ b/scripts/protocgen.sh @@ -38,5 +38,3 @@ cd .. # move proto files to the right places cp -r github.com/cosmos/cosmos-sdk/* ./ rm -rf github.com - -go mod tidy -compat=1.19 diff --git a/server/start.go b/server/start.go index 6fe23e4c2898..ec122c00f9e4 100644 --- a/server/start.go +++ b/server/start.go @@ -244,6 +244,10 @@ func startStandAlone(ctx *Context, appCreator types.AppCreator) error { if err = svr.Stop(); err != nil { tmos.Exit(err.Error()) } + + if err = app.Close(); err != nil { + tmos.Exit(err.Error()) + } }() // Wait for SIGINT or SIGTERM signal @@ -485,6 +489,7 @@ func startInProcess(ctx *Context, clientCtx client.Context, appCreator types.App defer func() { if tmNode != nil && tmNode.IsRunning() { _ = tmNode.Stop() + _ = app.Close() } if apiSrv != nil { diff --git a/server/tm_cmds.go b/server/tm_cmds.go index 2dc1ddc57336..9c070d5ef26c 100644 --- a/server/tm_cmds.go +++ b/server/tm_cmds.go @@ -5,14 +5,23 @@ package server import ( "fmt" + "github.com/tendermint/tendermint/light" + "github.com/tendermint/tendermint/node" + cmtstore "github.com/tendermint/tendermint/proto/tendermint/store" + sm "github.com/tendermint/tendermint/state" + "github.com/tendermint/tendermint/statesync" + "github.com/spf13/cobra" "github.com/tendermint/tendermint/p2p" pvm "github.com/tendermint/tendermint/privval" + "github.com/tendermint/tendermint/store" tversion "github.com/tendermint/tendermint/version" "sigs.k8s.io/yaml" "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" + "github.com/cosmos/cosmos-sdk/server/types" sdk "github.com/cosmos/cosmos-sdk/types" ) @@ -117,3 +126,91 @@ func VersionCmd() *cobra.Command { }, } } + +func BootstrapStateCmd(appCreator types.AppCreator) *cobra.Command { + cmd := &cobra.Command{ + Use: "bootstrap-state", + Short: "Bootstrap CometBFT state at an arbitrary block height using a light client", + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + serverCtx := GetServerContextFromCmd(cmd) + cfg := serverCtx.Config + + height, err := cmd.Flags().GetInt64("height") + if err != nil { + return err + } + if height == 0 { + home := serverCtx.Viper.GetString(flags.FlagHome) + db, err := openDB(home, GetAppDBBackend(serverCtx.Viper)) + if err != nil { + return err + } + + app := appCreator(serverCtx.Logger, db, nil, serverCtx.Viper) + height = app.CommitMultiStore().LastCommitID().Version + } + + blockStoreDB, err := node.DefaultDBProvider(&node.DBContext{ID: "blockstore", Config: cfg}) + if err != nil { + return err + } + blockStore := store.NewBlockStore(blockStoreDB) + + stateDB, err := node.DefaultDBProvider(&node.DBContext{ID: "state", Config: cfg}) + if err != nil { + return err + } + stateStore := sm.NewStore(stateDB, sm.StoreOptions{ + DiscardABCIResponses: cfg.Storage.DiscardABCIResponses, + }) + + genState, _, err := node.LoadStateFromDBOrGenesisDocProvider(stateDB, node.DefaultGenesisDocProviderFunc(cfg)) + if err != nil { + return err + } + + stateProvider, err := statesync.NewLightClientStateProvider( + cmd.Context(), + genState.ChainID, genState.Version, genState.InitialHeight, + cfg.StateSync.RPCServers, light.TrustOptions{ + Period: cfg.StateSync.TrustPeriod, + Height: cfg.StateSync.TrustHeight, + Hash: cfg.StateSync.TrustHashBytes(), + }, serverCtx.Logger.With("module", "light")) + if err != nil { + return fmt.Errorf("failed to set up light client state provider: %w", err) + } + + state, err := stateProvider.State(cmd.Context(), uint64(height)) + if err != nil { + return fmt.Errorf("failed to get state: %w", err) + } + + commit, err := stateProvider.Commit(cmd.Context(), uint64(height)) + if err != nil { + return fmt.Errorf("failed to get commit: %w", err) + } + + if err := stateStore.Bootstrap(state); err != nil { + return fmt.Errorf("failed to bootstrap state: %w", err) + } + + if err := blockStore.SaveSeenCommit(state.LastBlockHeight, commit); err != nil { + return fmt.Errorf("failed to save seen commit: %w", err) + } + + store.SaveBlockStoreState(&cmtstore.BlockStoreState{ + // it breaks the invariant that blocks in range [Base, Height] must exists, but it do works in practice. + Base: state.LastBlockHeight, + Height: state.LastBlockHeight, + }, blockStoreDB) + + return nil + }, + } + + cmd.Flags().Int64("height", 0, "Block height to bootstrap state at, if not provided it uses the latest block height in app state") + + return cmd +} diff --git a/server/types/app.go b/server/types/app.go index abc4c739e5bb..d886936f75c5 100644 --- a/server/types/app.go +++ b/server/types/app.go @@ -15,6 +15,7 @@ import ( "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/server/api" "github.com/cosmos/cosmos-sdk/server/config" + "github.com/cosmos/cosmos-sdk/snapshots" sdk "github.com/cosmos/cosmos-sdk/types" ) @@ -55,6 +56,12 @@ type ( // Return the multistore instance CommitMultiStore() sdk.CommitMultiStore + + // Return the snapshot manager + SnapshotManager() *snapshots.Manager + + // Close is called in start cmd to gracefully cleanup resources. + Close() error } // ApplicationQueryService defines an extension of the Application interface diff --git a/server/util.go b/server/util.go index 98e82be44b03..b28e339bff5f 100644 --- a/server/util.go +++ b/server/util.go @@ -273,8 +273,9 @@ func interceptConfigs(rootViper *viper.Viper, customAppTemplate string, customCo // add server commands func AddCommands(rootCmd *cobra.Command, defaultNodeHome string, appCreator types.AppCreator, appExport types.AppExporter, addStartFlags types.ModuleInitFlags) { tendermintCmd := &cobra.Command{ - Use: "tendermint", - Short: "Tendermint subcommands", + Use: "tendermint", + Aliases: []string{"comet", "cometbft"}, + Short: "Tendermint subcommands", } tendermintCmd.AddCommand( @@ -284,6 +285,7 @@ func AddCommands(rootCmd *cobra.Command, defaultNodeHome string, appCreator type VersionCmd(), tmcmd.ResetAllCmd, tmcmd.ResetStateCmd, + BootstrapStateCmd(appCreator), ) startCmd := StartCmd(appCreator, defaultNodeHome) @@ -464,3 +466,22 @@ func DefaultBaseappOptions(appOpts types.AppOptions) []func(*baseapp.BaseApp) { baseapp.SetIAVLLazyLoading(cast.ToBool(appOpts.Get(FlagIAVLLazyLoading))), } } + +func GetSnapshotStore(appOpts types.AppOptions) (*snapshots.Store, error) { + homeDir := cast.ToString(appOpts.Get(flags.FlagHome)) + snapshotDir := filepath.Join(homeDir, "data", "snapshots") + if err := os.MkdirAll(snapshotDir, os.ModePerm); err != nil { + return nil, fmt.Errorf("failed to create snapshots directory: %w", err) + } + + snapshotDB, err := dbm.NewDB("metadata", GetAppDBBackend(appOpts), snapshotDir) + if err != nil { + return nil, err + } + snapshotStore, err := snapshots.NewStore(snapshotDB, snapshotDir) + if err != nil { + return nil, err + } + + return snapshotStore, nil +} diff --git a/simapp/simd/cmd/root.go b/simapp/simd/cmd/root.go index d8b71c6df53a..03261d516ca1 100644 --- a/simapp/simd/cmd/root.go +++ b/simapp/simd/cmd/root.go @@ -20,6 +20,7 @@ import ( "github.com/cosmos/cosmos-sdk/client/keys" "github.com/cosmos/cosmos-sdk/client/pruning" "github.com/cosmos/cosmos-sdk/client/rpc" + "github.com/cosmos/cosmos-sdk/client/snapshot" "github.com/cosmos/cosmos-sdk/server" serverconfig "github.com/cosmos/cosmos-sdk/server/config" servertypes "github.com/cosmos/cosmos-sdk/server/types" @@ -169,6 +170,7 @@ func initRootCmd(rootCmd *cobra.Command, encodingConfig params.EncodingConfig) { debug.Cmd(), config.Cmd(), pruning.PruningCmd(a.newApp), + snapshot.Cmd(a.newApp), ) server.AddCommands(rootCmd, simapp.DefaultNodeHome, a.newApp, a.appExport, addModuleInitFlags) diff --git a/simapp/state.go b/simapp/state.go index 168fb9190b2c..da45b75f7102 100644 --- a/simapp/state.go +++ b/simapp/state.go @@ -8,6 +8,7 @@ import ( "os" "time" + "github.com/gogo/protobuf/proto" tmjson "github.com/tendermint/tendermint/libs/json" tmtypes "github.com/tendermint/tendermint/types" @@ -27,14 +28,34 @@ import ( // It panics if the user provides files for both of them. // If a file is not given for the genesis or the sim params, it creates a randomized one. func AppStateFn(cdc codec.JSONCodec, simManager *module.SimulationManager) simtypes.AppStateFn { - return AppStateFnWithExtendedCb(cdc, simManager, nil) + genesisState := NewDefaultGenesisState(cdc) + return AppStateFnWithExtendedCb(cdc, simManager, genesisState, nil) } // AppStateFnWithExtendedCb returns the initial application state using a genesis or the simulation parameters. +// It calls AppStateFnWithExtendedCbs with nil moduleStateCb. +func AppStateFnWithExtendedCb( + cdc codec.JSONCodec, + simManager *module.SimulationManager, + genesisState map[string]json.RawMessage, + rawStateCb func(rawState map[string]json.RawMessage), +) simtypes.AppStateFn { + return AppStateFnWithExtendedCbs(cdc, simManager, genesisState, nil, rawStateCb) +} + +// AppStateFnWithExtendedCbs returns the initial application state using a genesis or the simulation parameters. // It panics if the user provides files for both of them. // If a file is not given for the genesis or the sim params, it creates a randomized one. -// cb is the callback function to extend rawState. -func AppStateFnWithExtendedCb(cdc codec.JSONCodec, simManager *module.SimulationManager, cb func(rawState map[string]json.RawMessage)) simtypes.AppStateFn { +// genesisState is the default genesis state of the whole app. +// moduleStateCb is the callback function to access moduleState. +// rawStateCb is the callback function to extend rawState. +func AppStateFnWithExtendedCbs( + cdc codec.JSONCodec, + simManager *module.SimulationManager, + genesisState map[string]json.RawMessage, + moduleStateCb func(moduleName string, genesisState interface{}), + rawStateCb func(rawState map[string]json.RawMessage), +) simtypes.AppStateFn { return func(r *rand.Rand, accs []simtypes.Account, config simtypes.Config, ) (appState json.RawMessage, simAccs []simtypes.Account, chainID string, genesisTimestamp time.Time) { if FlagGenesisTimeValue == 0 { @@ -132,8 +153,20 @@ func AppStateFnWithExtendedCb(cdc codec.JSONCodec, simManager *module.Simulation } // change appState back - rawState[stakingtypes.ModuleName] = cdc.MustMarshalJSON(stakingState) - rawState[banktypes.ModuleName] = cdc.MustMarshalJSON(bankState) + for name, state := range map[string]proto.Message{ + stakingtypes.ModuleName: stakingState, + banktypes.ModuleName: bankState, + } { + if moduleStateCb != nil { + moduleStateCb(name, state) + } + rawState[name] = cdc.MustMarshalJSON(state) + } + + // extend state from callback function + if rawStateCb != nil { + rawStateCb(rawState) + } // replace appstate appState, err = json.Marshal(rawState) diff --git a/snapshots/README.md b/snapshots/README.md index 1c80f05d5633..f9fccfc20f38 100644 --- a/snapshots/README.md +++ b/snapshots/README.md @@ -55,16 +55,16 @@ Snapshot settings are optional. However, if set, they have an effect on how prun persisting the heights that are multiples of `state-sync.snapshot-interval` until after the snapshot is complete. If pruning is enabled (not `pruning = "nothing"`), we avoid pruning heights that are multiples of -`state-sync.snapshot-interval` in the regular logic determined by the -pruning settings and applied after every `Commit()`. This is done to prevent a -height from being removed before a snapshot is complete. Therefore, we keep -such heights until after a snapshot is done. At this point, the height is sent to +`state-sync.snapshot-interval` in the regular logic determined by the +pruning settings and applied after every `Commit()`. This is done to prevent a +height from being removed before a snapshot is complete. Therefore, we keep +such heights until after a snapshot is done. At this point, the height is sent to the `pruning.Manager` to be pruned according to the pruning settings after the next `Commit()`. To illustrate, assume that we are currently at height 960 with `pruning-keep-recent = 50`, `pruning-interval = 10`, and `state-sync.snapshot-interval = 100`. Let's assume that the snapshot that was triggered at height `900` **just finishes**. Then, we can prune height -`900` right away (that is, when we call `Commit()` at height 960 because 900 is less than `960 - 50 = 910`. +`900` right away (that is, when we call `Commit()` at height 960 because 900 is less than `960 - 50 = 910`). Let's now assume that all conditions stay the same but the snapshot at height 900 is **not complete yet**. Then, we cannot prune it to avoid deleting a height that is still being snapshotted. Therefore, we keep track @@ -78,23 +78,22 @@ Note that in both examples, if we let current height = C, and previous height P P - `pruning-keep-recent` - `pruning-interval` <= h <= P - `pruning-keep-recent` -we can prune height h. In our first example, all heights 899 - 909 fall in this range and are pruned at height 960 as long as +we can prune height h. In our first example, all heights 899 - 909 fall in this range and are pruned at height 960 as long as h is not a snapshot height (E.g. 900). That is, we always use current height to determine at which height to prune (960) while we use previous to determine which heights are to be pruned (959 - 50 - 10 = 899-909 = 959 - 50). - ## Configuration * `state-sync.snapshot-interval` - * the interval at which to take snapshots. - * the value of 0 disables snapshots. - * if pruning is enabled, it is done after a snapshot is complete for the heights that are multiples of this interval. + * the interval at which to take snapshots. + * the value of 0 disables snapshots. + * if pruning is enabled, it is done after a snapshot is complete for the heights that are multiples of this interval. * `state-sync.snapshot-keep-recent`: - * the number of recent snapshots to keep. - * 0 means keep all. + * the number of recent snapshots to keep. + * 0 means keep all. ## Snapshot Metadata diff --git a/snapshots/manager.go b/snapshots/manager.go index 05cbad3f5b30..b92a2b5b82d0 100644 --- a/snapshots/manager.go +++ b/snapshots/manager.go @@ -7,6 +7,7 @@ import ( "fmt" "io" "math" + "os" "sort" "sync" @@ -38,12 +39,12 @@ type Manager struct { multistore types.Snapshotter logger log.Logger - mtx sync.Mutex - operation operation - chRestore chan<- io.ReadCloser - chRestoreDone <-chan restoreDone - restoreChunkHashes [][]byte - restoreChunkIndex uint32 + mtx sync.Mutex + operation operation + chRestore chan<- uint32 + chRestoreDone <-chan restoreDone + restoreSnapshot *types.Snapshot + restoreChunkIndex uint32 } // operation represents a Manager operation. Only one operation can be in progress at a time. @@ -61,7 +62,8 @@ const ( opPrune operation = "prune" opRestore operation = "restore" - chunkBufferSize = 4 + chunkBufferSize = 4 + chunkIDBufferSize = 1024 snapshotMaxItemSize = int(64e6) // SDK has no key/value size limit, so we set an arbitrary limit ) @@ -131,7 +133,7 @@ func (m *Manager) endLocked() { m.chRestore = nil } m.chRestoreDone = nil - m.restoreChunkHashes = nil + m.restoreSnapshot = nil m.restoreChunkIndex = 0 } @@ -284,11 +286,18 @@ func (m *Manager) Restore(snapshot types.Snapshot) error { } // Start an asynchronous snapshot restoration, passing chunks and completion status via channels. - chChunks := make(chan io.ReadCloser, chunkBufferSize) + chChunkIDs := make(chan uint32, chunkIDBufferSize) chDone := make(chan restoreDone, 1) + dir := m.store.pathSnapshot(snapshot.Height, snapshot.Format) + if err := os.MkdirAll(dir, 0o750); err != nil { + return sdkerrors.Wrapf(err, "failed to create snapshot directory %q", dir) + } + + chChunks := m.loadChunkStream(snapshot.Height, snapshot.Format, chChunkIDs) + go func() { - err := m.restoreSnapshot(snapshot, chChunks) + err := m.doRestoreSnapshot(snapshot, chChunks) chDone <- restoreDone{ complete: err == nil, err: err, @@ -296,15 +305,38 @@ func (m *Manager) Restore(snapshot types.Snapshot) error { close(chDone) }() - m.chRestore = chChunks + m.chRestore = chChunkIDs m.chRestoreDone = chDone - m.restoreChunkHashes = snapshot.Metadata.ChunkHashes + m.restoreSnapshot = &snapshot m.restoreChunkIndex = 0 return nil } -// restoreSnapshot do the heavy work of snapshot restoration after preliminary checks on request have passed. -func (m *Manager) restoreSnapshot(snapshot types.Snapshot, chChunks <-chan io.ReadCloser) error { +func (m *Manager) loadChunkStream(height uint64, format uint32, chunkIDs <-chan uint32) <-chan io.ReadCloser { + chunks := make(chan io.ReadCloser, chunkBufferSize) + go func() { + defer close(chunks) + + for chunkID := range chunkIDs { + chunk, err := m.store.loadChunkFile(height, format, chunkID) + if err != nil { + m.logger.Error("load chunk file failed", "height", height, "format", format, "chunk", chunkID, "err", err) + break + } + chunks <- chunk + } + }() + + return chunks +} + +// doRestoreSnapshot do the heavy work of snapshot restoration after preliminary checks on request have passed. +func (m *Manager) doRestoreSnapshot(snapshot types.Snapshot, chChunks <-chan io.ReadCloser) error { + dir := m.store.pathSnapshot(snapshot.Height, snapshot.Format) + if err := os.MkdirAll(dir, 0o750); err != nil { + return sdkerrors.Wrapf(err, "failed to create snapshot directory %q", dir) + } + streamReader, err := NewStreamReader(chChunks) if err != nil { return err @@ -348,7 +380,7 @@ func (m *Manager) RestoreChunk(chunk []byte) (bool, error) { return false, sdkerrors.Wrap(sdkerrors.ErrLogic, "no restore operation in progress") } - if int(m.restoreChunkIndex) >= len(m.restoreChunkHashes) { + if int(m.restoreChunkIndex) >= len(m.restoreSnapshot.Metadata.ChunkHashes) { return false, sdkerrors.Wrap(sdkerrors.ErrLogic, "received unexpected chunk") } @@ -365,19 +397,30 @@ func (m *Manager) RestoreChunk(chunk []byte) (bool, error) { // Verify the chunk hash. hash := sha256.Sum256(chunk) - expected := m.restoreChunkHashes[m.restoreChunkIndex] + expected := m.restoreSnapshot.Metadata.ChunkHashes[m.restoreChunkIndex] if !bytes.Equal(hash[:], expected) { return false, sdkerrors.Wrapf(types.ErrChunkHashMismatch, "expected %x, got %x", hash, expected) } + if err := m.store.saveChunkContent(chunk, m.restoreChunkIndex, m.restoreSnapshot); err != nil { + return false, sdkerrors.Wrapf(err, "save chunk content %d", m.restoreChunkIndex) + } + // Pass the chunk to the restore, and wait for completion if it was the final one. - m.chRestore <- io.NopCloser(bytes.NewReader(chunk)) + m.chRestore <- m.restoreChunkIndex m.restoreChunkIndex++ - if int(m.restoreChunkIndex) >= len(m.restoreChunkHashes) { + if int(m.restoreChunkIndex) >= len(m.restoreSnapshot.Metadata.ChunkHashes) { close(m.chRestore) m.chRestore = nil + + // the chunks are all written into files, we can save the snapshot to the db, + // even if the restoration may not completed yet. + if err := m.store.saveSnapshot(m.restoreSnapshot); err != nil { + return false, sdkerrors.Wrap(err, "save restoring snapshot") + } + done := <-m.chRestoreDone m.endLocked() if done.err != nil { @@ -386,11 +429,35 @@ func (m *Manager) RestoreChunk(chunk []byte) (bool, error) { if !done.complete { return false, sdkerrors.Wrap(sdkerrors.ErrLogic, "restore ended prematurely") } + return true, nil } return false, nil } +// RestoreLocalSnapshot restores app state from a local snapshot. +func (m *Manager) RestoreLocalSnapshot(height uint64, format uint32) error { + snapshot, ch, err := m.store.Load(height, format) + if err != nil { + return err + } + + if snapshot == nil { + return fmt.Errorf("snapshot doesn't exist, height: %d, format: %d", height, format) + } + + m.mtx.Lock() + defer m.mtx.Unlock() + + err = m.beginLocked(opRestore) + if err != nil { + return err + } + defer m.endLocked() + + return m.doRestoreSnapshot(*snapshot, ch) +} + // sortedExtensionNames sort extension names for deterministic iteration. func (m *Manager) sortedExtensionNames() []string { names := make([]string, 0, len(m.extensions)) diff --git a/snapshots/manager_test.go b/snapshots/manager_test.go index b71043022827..d379f09cb9f1 100644 --- a/snapshots/manager_test.go +++ b/snapshots/manager_test.go @@ -205,6 +205,13 @@ func TestManager_Restore(t *testing.T) { assert.Equal(t, expectItems, target.items) + // The snapshot is saved in local snapshot store + snapshots, err := store.List() + require.NoError(t, err) + snapshot := snapshots[0] + require.Equal(t, uint64(3), snapshot.Height) + require.Equal(t, types.CurrentFormat, snapshot.Format) + // Starting a new restore should fail now, because the target already has contents. err = manager.Restore(types.Snapshot{ Height: 3, diff --git a/snapshots/store.go b/snapshots/store.go index 8105938b80f1..254686e631b4 100644 --- a/snapshots/store.go +++ b/snapshots/store.go @@ -3,6 +3,7 @@ package snapshots import ( "crypto/sha256" "encoding/binary" + "hash" "io" "math" "os" @@ -14,6 +15,7 @@ import ( db "github.com/tendermint/tm-db" "github.com/cosmos/cosmos-sdk/snapshots/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" ) @@ -164,8 +166,8 @@ func (s *Store) Load(height uint64, format uint32) (*types.Snapshot, <-chan io.R // LoadChunk loads a chunk from disk, or returns nil if it does not exist. The caller must call // Close() on it when done. -func (s *Store) LoadChunk(height uint64, format uint32, chunk uint32) (io.ReadCloser, error) { - path := s.pathChunk(height, format, chunk) +func (s *Store) LoadChunk(height uint64, format, chunk uint32) (io.ReadCloser, error) { + path := s.PathChunk(height, format, chunk) file, err := os.Open(path) if os.IsNotExist(err) { return nil, nil @@ -174,8 +176,8 @@ func (s *Store) LoadChunk(height uint64, format uint32, chunk uint32) (io.ReadCl } // loadChunkFile loads a chunk from disk, and errors if it does not exist. -func (s *Store) loadChunkFile(height uint64, format uint32, chunk uint32) (io.ReadCloser, error) { - path := s.pathChunk(height, format, chunk) +func (s *Store) loadChunkFile(height uint64, format, chunk uint32) (io.ReadCloser, error) { + path := s.PathChunk(height, format, chunk) return os.Open(path) } @@ -259,33 +261,16 @@ func (s *Store) Save( snapshotHasher := sha256.New() chunkHasher := sha256.New() for chunkBody := range chunks { - defer chunkBody.Close() // nolint: staticcheck + defer chunkBody.Close() //nolint:staticcheck dir := s.pathSnapshot(height, format) err = os.MkdirAll(dir, 0o755) if err != nil { return nil, sdkerrors.Wrapf(err, "failed to create snapshot directory %q", dir) } - path := s.pathChunk(height, format, index) - file, err := os.Create(path) - if err != nil { - return nil, sdkerrors.Wrapf(err, "failed to create snapshot chunk file %q", path) - } - defer file.Close() // nolint: staticcheck - chunkHasher.Reset() - _, err = io.Copy(io.MultiWriter(file, chunkHasher, snapshotHasher), chunkBody) - if err != nil { - return nil, sdkerrors.Wrapf(err, "failed to generate snapshot chunk %v", index) - } - err = file.Close() - if err != nil { - return nil, sdkerrors.Wrapf(err, "failed to close snapshot chunk %v", index) + if err := s.saveChunk(chunkBody, index, snapshot, chunkHasher, snapshotHasher); err != nil { + return nil, err } - err = chunkBody.Close() - if err != nil { - return nil, sdkerrors.Wrapf(err, "failed to close snapshot chunk %v", index) - } - snapshot.Metadata.ChunkHashes = append(snapshot.Metadata.ChunkHashes, chunkHasher.Sum(nil)) index++ } snapshot.Chunks = index @@ -293,6 +278,42 @@ func (s *Store) Save( return snapshot, s.saveSnapshot(snapshot) } +// saveChunk saves the given chunkBody with the given index to its appropriate path on disk. +// The hash of the chunk is appended to the snapshot's metadata, +// and the overall snapshot hash is updated with the chunk content too. +func (s *Store) saveChunk(chunkBody io.ReadCloser, index uint32, snapshot *types.Snapshot, chunkHasher, snapshotHasher hash.Hash) error { + defer chunkBody.Close() + + path := s.PathChunk(snapshot.Height, snapshot.Format, index) + chunkFile, err := os.Create(path) + if err != nil { + return sdkerrors.Wrapf(err, "failed to create snapshot chunk file %q", path) + } + defer chunkFile.Close() + + chunkHasher.Reset() + if _, err := io.Copy(io.MultiWriter(chunkFile, chunkHasher, snapshotHasher), chunkBody); err != nil { + return sdkerrors.Wrapf(err, "failed to generate snapshot chunk %d", index) + } + + if err := chunkFile.Close(); err != nil { + return sdkerrors.Wrapf(err, "failed to close snapshot chunk file %d", index) + } + + if err := chunkBody.Close(); err != nil { + return sdkerrors.Wrapf(err, "failed to close snapshot chunk body %d", index) + } + + snapshot.Metadata.ChunkHashes = append(snapshot.Metadata.ChunkHashes, chunkHasher.Sum(nil)) + return nil +} + +// saveChunkContent save the chunk to disk +func (s *Store) saveChunkContent(chunk []byte, index uint32, snapshot *types.Snapshot) error { + path := s.PathChunk(snapshot.Height, snapshot.Format, index) + return os.WriteFile(path, chunk, 0o600) +} + // saveSnapshot saves snapshot metadata to the database. func (s *Store) saveSnapshot(snapshot *types.Snapshot) error { value, err := proto.Marshal(snapshot) @@ -313,8 +334,8 @@ func (s *Store) pathSnapshot(height uint64, format uint32) string { return filepath.Join(s.pathHeight(height), strconv.FormatUint(uint64(format), 10)) } -// pathChunk generates a snapshot chunk path. -func (s *Store) pathChunk(height uint64, format uint32, chunk uint32) string { +// PathChunk generates a snapshot chunk path. +func (s *Store) PathChunk(height uint64, format, chunk uint32) string { return filepath.Join(s.pathSnapshot(height, format), strconv.FormatUint(uint64(chunk), 10)) } diff --git a/store/iavl/store.go b/store/iavl/store.go index 3cf6c1dedbf2..7517f934f4de 100644 --- a/store/iavl/store.go +++ b/store/iavl/store.go @@ -111,7 +111,7 @@ func UnsafeNewStore(tree *iavl.MutableTree) *Store { // Any mutable operations executed will result in a panic. func (st *Store) GetImmutable(version int64) (*Store, error) { if !st.VersionExists(version) { - return &Store{tree: &immutableTree{&iavl.ImmutableTree{}}}, nil + return nil, fmt.Errorf("version mismatch on immutable IAVL tree; version does not exist. Version has either been pruned, or is for a future block height") } iTree, err := st.tree.GetImmutable(version) diff --git a/store/iavl/store_test.go b/store/iavl/store_test.go index dabe1e37f630..8379779c158b 100644 --- a/store/iavl/store_test.go +++ b/store/iavl/store_test.go @@ -127,7 +127,7 @@ func TestGetImmutable(t *testing.T) { require.Nil(t, err) _, err = store.GetImmutable(cID.Version + 1) - require.NoError(t, err) + require.Error(t, err) newStore, err := store.GetImmutable(cID.Version - 1) require.NoError(t, err) diff --git a/store/rootmulti/store.go b/store/rootmulti/store.go index 74915695ab40..7397abd0424e 100644 --- a/store/rootmulti/store.go +++ b/store/rootmulti/store.go @@ -481,6 +481,8 @@ func (rs *Store) CacheMultiStore() types.CacheMultiStore { // iterating at past heights. func (rs *Store) CacheMultiStoreWithVersion(version int64) (types.CacheMultiStore, error) { cachedStores := make(map[types.StoreKey]types.CacheWrapper) + var commitInfo *types.CommitInfo + storeInfos := map[string]bool{} for key, store := range rs.stores { var cacheStore types.KVStore switch store.GetStoreType() { @@ -493,9 +495,30 @@ func (rs *Store) CacheMultiStoreWithVersion(version int64) (types.CacheMultiStor // version does not exist or is pruned, an error should be returned. var err error cacheStore, err = store.(*iavl.Store).GetImmutable(version) + // if we got error from loading a module store + // we fetch commit info of this version + // we use commit info to check if the store existed at this version or not if err != nil { - return nil, err + if commitInfo == nil { + var errCommitInfo error + commitInfo, errCommitInfo = getCommitInfo(rs.db, version) + + if errCommitInfo != nil { + return nil, errCommitInfo + } + + for _, storeInfo := range commitInfo.StoreInfos { + storeInfos[storeInfo.Name] = true + } + } + + // If the store existed at this version, it means there's actually an error + // getting the root store at this version. + if storeInfos[key.Name()] { + return nil, err + } } + default: cacheStore = store } diff --git a/store/rootmulti/store_test.go b/store/rootmulti/store_test.go index 0e78e0f95bed..69e773be1a80 100644 --- a/store/rootmulti/store_test.go +++ b/store/rootmulti/store_test.go @@ -88,7 +88,7 @@ func TestCacheMultiStoreWithVersion(t *testing.T) { // require no failure when given an invalid or pruned version _, err = ms.CacheMultiStoreWithVersion(cID.Version + 1) - require.NoError(t, err) + require.Error(t, err) // require a valid version can be cache-loaded cms, err := ms.CacheMultiStoreWithVersion(cID.Version) @@ -99,6 +99,17 @@ func TestCacheMultiStoreWithVersion(t *testing.T) { require.NotNil(t, kvStore) require.Equal(t, kvStore.Get(k), v) + // add new module stores (store4 and store5) to multi stores and commit + ms.MountStoreWithDB(types.NewKVStoreKey("store4"), types.StoreTypeIAVL, nil) + ms.MountStoreWithDB(types.NewKVStoreKey("store5"), types.StoreTypeIAVL, nil) + err = ms.LoadLatestVersionAndUpgrade(&types.StoreUpgrades{Added: []string{"store4", "store5"}}) + require.NoError(t, err) + ms.Commit() + + // cache multistore of version before adding store4 should works + _, err = ms.CacheMultiStoreWithVersion(1) + require.NoError(t, err) + // require we cannot commit (write) to a cache-versioned multi-store require.Panics(t, func() { kvStore.Set(k, []byte("newValue")) @@ -482,9 +493,9 @@ func TestMultiStore_Pruning(t *testing.T) { saved []int64 }{ {"prune nothing", 10, pruningtypes.NewPruningOptions(pruningtypes.PruningNothing), nil, []int64{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}}, - {"prune everything", 10, pruningtypes.NewPruningOptions(pruningtypes.PruningEverything), []int64{1, 2, 3, 4, 5, 6, 7, 8, 9}, []int64{10}}, - {"prune some; no batch", 10, pruningtypes.NewCustomPruningOptions(2, 1), []int64{1, 2, 4, 5, 7}, []int64{3, 6, 8, 9, 10}}, - {"prune some; small batch", 10, pruningtypes.NewCustomPruningOptions(2, 3), []int64{1, 2, 4, 5}, []int64{3, 6, 7, 8, 9, 10}}, + {"prune everything", 12, pruningtypes.NewPruningOptions(pruningtypes.PruningEverything), []int64{1, 2, 3, 4, 5, 6, 7}, []int64{8, 9, 10, 11, 12}}, + {"prune some; no batch", 10, pruningtypes.NewCustomPruningOptions(2, 1), []int64{1, 2, 3, 4, 6, 5, 7}, []int64{8, 9, 10}}, + {"prune some; small batch", 10, pruningtypes.NewCustomPruningOptions(2, 3), []int64{1, 2, 3, 4, 5, 6}, []int64{7, 8, 9, 10}}, {"prune some; large batch", 10, pruningtypes.NewCustomPruningOptions(2, 11), nil, []int64{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}}, } @@ -502,12 +513,12 @@ func TestMultiStore_Pruning(t *testing.T) { for _, v := range tc.saved { _, err := ms.CacheMultiStoreWithVersion(v) - require.NoError(t, err, "expected error when loading height: %d", v) + require.NoError(t, err, "expected no error when loading height: %d", v) } for _, v := range tc.deleted { _, err := ms.CacheMultiStoreWithVersion(v) - require.NoError(t, err, "expected error when loading height: %d", v) + require.Error(t, err, "expected error when loading height: %d", v) } }) } diff --git a/types/simulation/types.go b/types/simulation/types.go index 199f47fa38e2..a152413f3c07 100644 --- a/types/simulation/types.go +++ b/types/simulation/types.go @@ -161,6 +161,10 @@ type AppStateFn func(r *rand.Rand, accs []Account, config Config) ( appState json.RawMessage, accounts []Account, chainId string, genesisTimestamp time.Time, ) +// AppStateFnWithExtendedCb returns the app state json bytes and the genesis accounts +// Deprecated: Use AppStateFn instead. This will be removed in a future relase. +type AppStateFnWithExtendedCb AppStateFn + // RandomAccountFn returns a slice of n random simulation accounts type RandomAccountFn func(r *rand.Rand, n int) []Account diff --git a/x/auth/vesting/client/cli/tx.go b/x/auth/vesting/client/cli/tx.go index 3c88d04500fa..f2ef3ba67fe7 100644 --- a/x/auth/vesting/client/cli/tx.go +++ b/x/auth/vesting/client/cli/tx.go @@ -142,7 +142,7 @@ func NewMsgCreatePeriodicVestingAccountCmd() *cobra.Command { An array of coin strings and unix epoch times for coins to vest { "start_time": 1625204910, -"period":[ +"periods":[ { "coins": "10test", "length_seconds":2592000 //30 days diff --git a/x/auth/vesting/types/msgs.go b/x/auth/vesting/types/msgs.go index fbce860cede4..f2194af5690b 100644 --- a/x/auth/vesting/types/msgs.go +++ b/x/auth/vesting/types/msgs.go @@ -182,6 +182,14 @@ func (msg MsgCreatePeriodicVestingAccount) ValidateBasic() error { } for i, period := range msg.VestingPeriods { + if !period.Amount.IsValid() { + return sdkerrors.ErrInvalidCoins.Wrap(period.Amount.String()) + } + + if !period.Amount.IsAllPositive() { + return sdkerrors.ErrInvalidCoins.Wrap(period.Amount.String()) + } + if period.Length < 1 { return fmt.Errorf("invalid period length of %d in period %d, length must be greater than 0", period.Length, i) } diff --git a/x/auth/vesting/types/tx.pb.go b/x/auth/vesting/types/tx.pb.go index 96b06cdb922b..0165ea83312e 100644 --- a/x/auth/vesting/types/tx.pb.go +++ b/x/auth/vesting/types/tx.pb.go @@ -38,8 +38,9 @@ type MsgCreateVestingAccount struct { FromAddress string `protobuf:"bytes,1,opt,name=from_address,json=fromAddress,proto3" json:"from_address,omitempty"` ToAddress string `protobuf:"bytes,2,opt,name=to_address,json=toAddress,proto3" json:"to_address,omitempty"` Amount github_com_cosmos_cosmos_sdk_types.Coins `protobuf:"bytes,3,rep,name=amount,proto3,castrepeated=github.com/cosmos/cosmos-sdk/types.Coins" json:"amount"` - EndTime int64 `protobuf:"varint,4,opt,name=end_time,json=endTime,proto3" json:"end_time,omitempty"` - Delayed bool `protobuf:"varint,5,opt,name=delayed,proto3" json:"delayed,omitempty"` + // end of vesting as unix time (in seconds). + EndTime int64 `protobuf:"varint,4,opt,name=end_time,json=endTime,proto3" json:"end_time,omitempty"` + Delayed bool `protobuf:"varint,5,opt,name=delayed,proto3" json:"delayed,omitempty"` } func (m *MsgCreateVestingAccount) Reset() { *m = MsgCreateVestingAccount{} } @@ -257,8 +258,9 @@ var xxx_messageInfo_MsgCreatePermanentLockedAccountResponse proto.InternalMessag // // Since: cosmos-sdk 0.46 type MsgCreatePeriodicVestingAccount struct { - FromAddress string `protobuf:"bytes,1,opt,name=from_address,json=fromAddress,proto3" json:"from_address,omitempty"` - ToAddress string `protobuf:"bytes,2,opt,name=to_address,json=toAddress,proto3" json:"to_address,omitempty"` + FromAddress string `protobuf:"bytes,1,opt,name=from_address,json=fromAddress,proto3" json:"from_address,omitempty"` + ToAddress string `protobuf:"bytes,2,opt,name=to_address,json=toAddress,proto3" json:"to_address,omitempty"` + // start of vesting as unix time (in seconds). StartTime int64 `protobuf:"varint,3,opt,name=start_time,json=startTime,proto3" json:"start_time,omitempty"` VestingPeriods []Period `protobuf:"bytes,4,rep,name=vesting_periods,json=vestingPeriods,proto3" json:"vesting_periods"` } diff --git a/x/auth/vesting/types/vesting.pb.go b/x/auth/vesting/types/vesting.pb.go index 1404b5891cc6..9c05fa2dff68 100644 --- a/x/auth/vesting/types/vesting.pb.go +++ b/x/auth/vesting/types/vesting.pb.go @@ -33,7 +33,8 @@ type BaseVestingAccount struct { OriginalVesting github_com_cosmos_cosmos_sdk_types.Coins `protobuf:"bytes,2,rep,name=original_vesting,json=originalVesting,proto3,castrepeated=github.com/cosmos/cosmos-sdk/types.Coins" json:"original_vesting"` DelegatedFree github_com_cosmos_cosmos_sdk_types.Coins `protobuf:"bytes,3,rep,name=delegated_free,json=delegatedFree,proto3,castrepeated=github.com/cosmos/cosmos-sdk/types.Coins" json:"delegated_free"` DelegatedVesting github_com_cosmos_cosmos_sdk_types.Coins `protobuf:"bytes,4,rep,name=delegated_vesting,json=delegatedVesting,proto3,castrepeated=github.com/cosmos/cosmos-sdk/types.Coins" json:"delegated_vesting"` - EndTime int64 `protobuf:"varint,5,opt,name=end_time,json=endTime,proto3" json:"end_time,omitempty"` + // Vesting end time, as unix timestamp (in seconds). + EndTime int64 `protobuf:"varint,5,opt,name=end_time,json=endTime,proto3" json:"end_time,omitempty"` } func (m *BaseVestingAccount) Reset() { *m = BaseVestingAccount{} } @@ -72,7 +73,8 @@ var xxx_messageInfo_BaseVestingAccount proto.InternalMessageInfo // continuously vests by unlocking coins linearly with respect to time. type ContinuousVestingAccount struct { *BaseVestingAccount `protobuf:"bytes,1,opt,name=base_vesting_account,json=baseVestingAccount,proto3,embedded=base_vesting_account" json:"base_vesting_account,omitempty"` - StartTime int64 `protobuf:"varint,2,opt,name=start_time,json=startTime,proto3" json:"start_time,omitempty"` + // Vesting start time, as unix timestamp (in seconds). + StartTime int64 `protobuf:"varint,2,opt,name=start_time,json=startTime,proto3" json:"start_time,omitempty"` } func (m *ContinuousVestingAccount) Reset() { *m = ContinuousVestingAccount{} } @@ -148,6 +150,7 @@ var xxx_messageInfo_DelayedVestingAccount proto.InternalMessageInfo // Period defines a length of time and amount of coins that will vest. type Period struct { + // Period duration in seconds. Length int64 `protobuf:"varint,1,opt,name=length,proto3" json:"length,omitempty"` Amount github_com_cosmos_cosmos_sdk_types.Coins `protobuf:"bytes,2,rep,name=amount,proto3,castrepeated=github.com/cosmos/cosmos-sdk/types.Coins" json:"amount"` } diff --git a/x/distribution/keeper/delegation.go b/x/distribution/keeper/delegation.go index a5531e33f775..f94e1a73b4be 100644 --- a/x/distribution/keeper/delegation.go +++ b/x/distribution/keeper/delegation.go @@ -205,6 +205,7 @@ func (k Keeper) withdrawDelegationRewards(ctx sdk.Context, val stakingtypes.Vali types.EventTypeWithdrawRewards, sdk.NewAttribute(sdk.AttributeKeyAmount, emittedRewards.String()), sdk.NewAttribute(types.AttributeKeyValidator, val.GetOperator().String()), + sdk.NewAttribute(types.AttributeKeyDelegator, del.GetDelegatorAddr().String()), ), ) diff --git a/x/distribution/types/events.go b/x/distribution/types/events.go index ce4c0ef62e3c..9ca631db0076 100644 --- a/x/distribution/types/events.go +++ b/x/distribution/types/events.go @@ -11,6 +11,6 @@ const ( AttributeKeyWithdrawAddress = "withdraw_address" AttributeKeyValidator = "validator" - - AttributeValueCategory = ModuleName + AttributeKeyDelegator = "delegator" + AttributeValueCategory = ModuleName ) diff --git a/x/gov/migrations/v046/convert.go b/x/gov/migrations/v046/convert.go index e368a0b2b2b6..2c632a4124a6 100644 --- a/x/gov/migrations/v046/convert.go +++ b/x/gov/migrations/v046/convert.go @@ -49,7 +49,7 @@ func ConvertToLegacyProposal(proposal v1.Proposal) (v1beta1.Proposal, error) { return v1beta1.Proposal{}, err } if len(msgs) != 1 { - return v1beta1.Proposal{}, sdkerrors.ErrInvalidType.Wrap("can't convert a gov/v1 Proposal to gov/v1beta1 Proposal when amount of proposal messages is more than one") + return v1beta1.Proposal{}, sdkerrors.ErrInvalidType.Wrap("can't convert a gov/v1 Proposal to gov/v1beta1 Proposal when amount of proposal messages not exactly one") } if legacyMsg, ok := msgs[0].(*v1.MsgExecLegacyContent); ok { // check that the content struct can be unmarshalled diff --git a/x/group/client/cli/query.go b/x/group/client/cli/query.go index 1535566f525d..e7b866d92508 100644 --- a/x/group/client/cli/query.go +++ b/x/group/client/cli/query.go @@ -33,6 +33,7 @@ func QueryCmd(name string) *cobra.Command { QueryVotesByVoterCmd(), QueryGroupsByMemberCmd(), QueryTallyResultCmd(), + QueryGroupsCmd(), ) return queryCmd @@ -504,3 +505,37 @@ func QueryVotesByVoterCmd() *cobra.Command { return cmd } + +func QueryGroupsCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "groups", + Short: "Query for groups present in the state", + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + + pageReq, err := client.ReadPageRequest(cmd.Flags()) + if err != nil { + return err + } + + queryClient := group.NewQueryClient(clientCtx) + + res, err := queryClient.Groups(cmd.Context(), &group.QueryGroupsRequest{ + Pagination: pageReq, + }) + if err != nil { + return err + } + + return clientCtx.PrintProto(res) + }, + } + + flags.AddQueryFlagsToCmd(cmd) + flags.AddPaginationFlagsToCmd(cmd, "groups") + + return cmd +} diff --git a/x/group/client/testutil/query.go b/x/group/client/testutil/query.go index 74c152b50978..28ec0746be81 100644 --- a/x/group/client/testutil/query.go +++ b/x/group/client/testutil/query.go @@ -149,6 +149,55 @@ func (s *IntegrationTestSuite) TestQueryGroupsByMembers() { } } +func (s *IntegrationTestSuite) TestQueryGroups() { + val := s.network.Validators[0] + clientCtx := val.ClientCtx + require := s.Require() + + testCases := []struct { + name string + args []string + expectErr bool + expectErrMsg string + numItems int + expectGroups []*group.GroupInfo + }{ + { + name: "valid req", + args: []string{fmt.Sprintf("--%s=json", tmcli.OutputFlag)}, + expectErr: false, + numItems: 5, + }, + { + name: "valid req with pagination", + args: []string{ + "--limit=2", + fmt.Sprintf("--%s=json", tmcli.OutputFlag), + }, + expectErr: false, + numItems: 2, + }, + } + + for _, tc := range testCases { + tc := tc + s.Run(tc.name, func() { + cmd := client.QueryGroupsCmd() + out, err := cli.ExecTestCLICmd(clientCtx, cmd, tc.args) + if tc.expectErr { + require.Contains(out.String(), tc.expectErrMsg) + } else { + require.NoError(err, out.String()) + + var resp group.QueryGroupsResponse + val.ClientCtx.Codec.MustUnmarshalJSON(out.Bytes(), &resp) + + require.Len(resp.Groups, tc.numItems) + } + }) + } +} + func (s *IntegrationTestSuite) TestQueryGroupMembers() { val := s.network.Validators[0] clientCtx := val.ClientCtx diff --git a/x/group/events.pb.go b/x/group/events.pb.go index 3cbcb2d491d6..c724b905da7c 100644 --- a/x/group/events.pb.go +++ b/x/group/events.pb.go @@ -464,6 +464,70 @@ func (m *EventLeaveGroup) GetAddress() string { return "" } +// EventProposalPruned is an event emitted when a proposal is pruned. +type EventProposalPruned struct { + // proposal_id is the unique ID of the proposal. + ProposalId uint64 `protobuf:"varint,1,opt,name=proposal_id,json=proposalId,proto3" json:"proposal_id,omitempty"` + // status is the proposal status (UNSPECIFIED, SUBMITTED, ACCEPTED, REJECTED, ABORTED, WITHDRAWN). + Status ProposalStatus `protobuf:"varint,2,opt,name=status,proto3,enum=cosmos.group.v1.ProposalStatus" json:"status,omitempty"` + // tally_result is the proposal tally result (when applicable). + TallyResult *TallyResult `protobuf:"bytes,3,opt,name=tally_result,json=tallyResult,proto3" json:"tally_result,omitempty"` +} + +func (m *EventProposalPruned) Reset() { *m = EventProposalPruned{} } +func (m *EventProposalPruned) String() string { return proto.CompactTextString(m) } +func (*EventProposalPruned) ProtoMessage() {} +func (*EventProposalPruned) Descriptor() ([]byte, []int) { + return fileDescriptor_e8d753981546f032, []int{9} +} +func (m *EventProposalPruned) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *EventProposalPruned) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_EventProposalPruned.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *EventProposalPruned) XXX_Merge(src proto.Message) { + xxx_messageInfo_EventProposalPruned.Merge(m, src) +} +func (m *EventProposalPruned) XXX_Size() int { + return m.Size() +} +func (m *EventProposalPruned) XXX_DiscardUnknown() { + xxx_messageInfo_EventProposalPruned.DiscardUnknown(m) +} + +var xxx_messageInfo_EventProposalPruned proto.InternalMessageInfo + +func (m *EventProposalPruned) GetProposalId() uint64 { + if m != nil { + return m.ProposalId + } + return 0 +} + +func (m *EventProposalPruned) GetStatus() ProposalStatus { + if m != nil { + return m.Status + } + return PROPOSAL_STATUS_UNSPECIFIED +} + +func (m *EventProposalPruned) GetTallyResult() *TallyResult { + if m != nil { + return m.TallyResult + } + return nil +} + func init() { proto.RegisterType((*EventCreateGroup)(nil), "cosmos.group.v1.EventCreateGroup") proto.RegisterType((*EventUpdateGroup)(nil), "cosmos.group.v1.EventUpdateGroup") @@ -474,36 +538,41 @@ func init() { proto.RegisterType((*EventVote)(nil), "cosmos.group.v1.EventVote") proto.RegisterType((*EventExec)(nil), "cosmos.group.v1.EventExec") proto.RegisterType((*EventLeaveGroup)(nil), "cosmos.group.v1.EventLeaveGroup") + proto.RegisterType((*EventProposalPruned)(nil), "cosmos.group.v1.EventProposalPruned") } func init() { proto.RegisterFile("cosmos/group/v1/events.proto", fileDescriptor_e8d753981546f032) } var fileDescriptor_e8d753981546f032 = []byte{ - // 382 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x49, 0xce, 0x2f, 0xce, - 0xcd, 0x2f, 0xd6, 0x4f, 0x2f, 0xca, 0x2f, 0x2d, 0xd0, 0x2f, 0x33, 0xd4, 0x4f, 0x2d, 0x4b, 0xcd, - 0x2b, 0x29, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x87, 0xc8, 0xea, 0x81, 0x65, 0xf5, - 0xca, 0x0c, 0xa5, 0x24, 0x21, 0x02, 0xf1, 0x60, 0x69, 0x7d, 0xa8, 0x2c, 0x98, 0x23, 0x25, 0x8d, - 0x6e, 0x52, 0x49, 0x65, 0x41, 0x2a, 0x54, 0x52, 0x49, 0x97, 0x4b, 0xc0, 0x15, 0x64, 0xb0, 0x73, - 0x51, 0x6a, 0x62, 0x49, 0xaa, 0x3b, 0x48, 0x89, 0x90, 0x24, 0x17, 0x07, 0x58, 0x6d, 0x7c, 0x66, - 0x8a, 0x04, 0xa3, 0x02, 0xa3, 0x06, 0x4b, 0x10, 0x3b, 0x98, 0xef, 0x99, 0x02, 0x57, 0x1e, 0x5a, - 0x90, 0x42, 0x8c, 0x72, 0x1f, 0x2e, 0x31, 0x74, 0xd3, 0x03, 0xf2, 0x73, 0x32, 0x93, 0x2b, 0x85, - 0x8c, 0xb8, 0xd8, 0x13, 0x53, 0x52, 0x8a, 0x52, 0x8b, 0x8b, 0xc1, 0x7a, 0x38, 0x9d, 0x24, 0x2e, - 0x6d, 0xd1, 0x15, 0x81, 0xba, 0xdb, 0x11, 0x22, 0x13, 0x5c, 0x52, 0x94, 0x99, 0x97, 0x1e, 0x04, - 0x53, 0x08, 0x37, 0x0d, 0xc9, 0x72, 0x0a, 0x4c, 0x33, 0xe3, 0x12, 0x06, 0x9b, 0x16, 0x5c, 0x9a, - 0x94, 0x9b, 0x59, 0x12, 0x50, 0x94, 0x5f, 0x90, 0x5f, 0x9c, 0x98, 0x23, 0x24, 0xcf, 0xc5, 0x5d, - 0x00, 0x65, 0x23, 0x3c, 0xc4, 0x05, 0x13, 0xf2, 0x4c, 0x51, 0xb2, 0xe0, 0x12, 0x05, 0xeb, 0x0b, - 0xcf, 0x2c, 0xc9, 0x48, 0x29, 0x4a, 0x2c, 0x27, 0x5e, 0xa7, 0x0e, 0x17, 0x27, 0x58, 0x67, 0x58, - 0x7e, 0x49, 0x2a, 0x61, 0xd5, 0x8d, 0x8c, 0x50, 0xe5, 0xae, 0x15, 0xa9, 0xc9, 0x04, 0x95, 0x0b, - 0xd9, 0x73, 0xb1, 0x15, 0xa5, 0x16, 0x97, 0xe6, 0x94, 0x48, 0x30, 0x29, 0x30, 0x6a, 0xf0, 0x19, - 0xa9, 0xeb, 0xa1, 0x25, 0x11, 0x3d, 0x98, 0x43, 0x41, 0xe6, 0x95, 0x96, 0xe4, 0x17, 0x05, 0x81, - 0x95, 0x07, 0x41, 0xb5, 0x09, 0x09, 0x71, 0xb1, 0xe4, 0xe4, 0xa7, 0x17, 0x4b, 0x30, 0x83, 0x02, - 0x30, 0x08, 0xcc, 0x56, 0x4a, 0xe0, 0xe2, 0x07, 0x3b, 0xc1, 0x27, 0x35, 0xb1, 0x8c, 0x60, 0x6c, - 0x23, 0xc7, 0x02, 0x13, 0x91, 0xb1, 0xe0, 0x64, 0x77, 0xe2, 0x91, 0x1c, 0xe3, 0x85, 0x47, 0x72, - 0x8c, 0x0f, 0x1e, 0xc9, 0x31, 0x4e, 0x78, 0x2c, 0xc7, 0x70, 0xe1, 0xb1, 0x1c, 0xc3, 0x8d, 0xc7, - 0x72, 0x0c, 0x51, 0x2a, 0xe9, 0x99, 0x25, 0x19, 0xa5, 0x49, 0x7a, 0xc9, 0xf9, 0xb9, 0xd0, 0xf4, - 0x0c, 0xa5, 0x74, 0x8b, 0x53, 0xb2, 0xf5, 0x2b, 0x20, 0xc9, 0x39, 0x89, 0x0d, 0x9c, 0x8c, 0x8d, - 0x01, 0x01, 0x00, 0x00, 0xff, 0xff, 0x5b, 0xc0, 0x98, 0xf8, 0x2f, 0x03, 0x00, 0x00, + // 442 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x93, 0x4f, 0xef, 0xd2, 0x30, + 0x18, 0xc7, 0xe9, 0x4f, 0x02, 0x52, 0x8c, 0x98, 0xfa, 0x27, 0x03, 0xc9, 0x20, 0xc4, 0x44, 0x0e, + 0xb2, 0x05, 0x4c, 0xd4, 0x93, 0x44, 0x0c, 0x31, 0x24, 0x1c, 0xc8, 0xf0, 0x4f, 0xe2, 0x05, 0xc7, + 0xda, 0x8c, 0xc5, 0x41, 0x97, 0xb6, 0x9b, 0x70, 0xf4, 0x1d, 0xf8, 0x52, 0x3c, 0xf8, 0x22, 0x3c, + 0x12, 0x4f, 0x1e, 0x0d, 0xbc, 0x11, 0xb3, 0xae, 0x03, 0x82, 0x31, 0x23, 0xf9, 0x9d, 0x68, 0xfb, + 0xfd, 0x7c, 0xbf, 0x3c, 0x4f, 0x9f, 0x15, 0xd6, 0x1d, 0xca, 0x97, 0x94, 0x9b, 0x2e, 0xa3, 0x61, + 0x60, 0x46, 0x5d, 0x93, 0x44, 0x64, 0x25, 0xb8, 0x11, 0x30, 0x2a, 0x28, 0xaa, 0x24, 0xaa, 0x21, + 0x55, 0x23, 0xea, 0xd6, 0xaa, 0xc9, 0xc1, 0x4c, 0xca, 0xa6, 0x52, 0xe5, 0xa6, 0xf6, 0xf0, 0x3c, + 0x49, 0x6c, 0x02, 0xa2, 0xc4, 0x56, 0x07, 0xde, 0x19, 0xc6, 0xc1, 0xaf, 0x19, 0xb1, 0x05, 0x79, + 0x13, 0x23, 0xa8, 0x0a, 0x6f, 0x4a, 0x76, 0xe6, 0x61, 0x0d, 0x34, 0x41, 0x3b, 0x6f, 0x15, 0xe5, + 0x7e, 0x84, 0x0f, 0xf8, 0xbb, 0x00, 0x5f, 0x82, 0x8f, 0xe1, 0x83, 0xf3, 0xf4, 0x09, 0xf5, 0x3d, + 0x67, 0x83, 0x7a, 0xb0, 0x68, 0x63, 0xcc, 0x08, 0xe7, 0xd2, 0x53, 0x1a, 0x68, 0xbf, 0x7e, 0x74, + 0xee, 0xa9, 0xba, 0x5f, 0x25, 0xca, 0x54, 0x30, 0x6f, 0xe5, 0x5a, 0x29, 0x78, 0x48, 0x3b, 0xf9, + 0xf3, 0x6b, 0xa4, 0x3d, 0x83, 0x77, 0x65, 0xda, 0x34, 0x9c, 0x2f, 0x3d, 0x31, 0x61, 0x34, 0xa0, + 0xdc, 0xf6, 0x51, 0x03, 0x96, 0x03, 0xb5, 0x3e, 0x36, 0x04, 0xd3, 0xa3, 0x11, 0x6e, 0xbd, 0x80, + 0xf7, 0xa5, 0xef, 0x83, 0x27, 0x16, 0x98, 0xd9, 0x5f, 0x2e, 0x77, 0x3e, 0x81, 0x25, 0xe9, 0x7c, + 0x4f, 0x05, 0xc9, 0xa6, 0xbf, 0x02, 0x85, 0x0f, 0xd7, 0xc4, 0xc9, 0xc4, 0x51, 0x1f, 0x16, 0x18, + 0xe1, 0xa1, 0x2f, 0xb4, 0xab, 0x26, 0x68, 0xdf, 0xee, 0x3d, 0x36, 0xce, 0x3e, 0x11, 0x23, 0x2d, + 0x34, 0xce, 0x0b, 0x05, 0x65, 0x96, 0xc4, 0x2d, 0x65, 0x43, 0x08, 0xe6, 0x7d, 0xea, 0x72, 0xed, + 0x46, 0x7c, 0x81, 0x96, 0x5c, 0xb7, 0x3e, 0xc1, 0x8a, 0x2c, 0x61, 0x4c, 0xec, 0x28, 0x73, 0xda, + 0xa7, 0x53, 0xb8, 0xba, 0x74, 0x0a, 0xdf, 0x81, 0x1a, 0x43, 0x5a, 0xdd, 0x84, 0x85, 0x2b, 0x82, + 0xb3, 0xfb, 0x7d, 0x0e, 0x0b, 0x5c, 0xd8, 0x22, 0xe4, 0xaa, 0xdf, 0xc6, 0x7f, 0xfb, 0x9d, 0x4a, + 0xcc, 0x52, 0x38, 0xea, 0xc3, 0x5b, 0xc2, 0xf6, 0xfd, 0xcd, 0x4c, 0x5d, 0x57, 0xdc, 0x6f, 0xb9, + 0x57, 0xff, 0xc7, 0xfe, 0x36, 0x86, 0xd4, 0x1d, 0x95, 0xc5, 0x71, 0x33, 0x78, 0xf9, 0x73, 0xa7, + 0x83, 0xed, 0x4e, 0x07, 0x7f, 0x76, 0x3a, 0xf8, 0xb6, 0xd7, 0x73, 0xdb, 0xbd, 0x9e, 0xfb, 0xbd, + 0xd7, 0x73, 0x1f, 0x1f, 0xb9, 0x9e, 0x58, 0x84, 0x73, 0xc3, 0xa1, 0x4b, 0xf5, 0x04, 0xd5, 0x4f, + 0x87, 0xe3, 0xcf, 0xe6, 0x3a, 0x79, 0x81, 0xf3, 0x82, 0x7c, 0x79, 0x4f, 0xff, 0x06, 0x00, 0x00, + 0xff, 0xff, 0xa5, 0x1a, 0x1c, 0xb9, 0xe2, 0x03, 0x00, 0x00, } func (m *EventCreateGroup) Marshal() (dAtA []byte, err error) { @@ -781,6 +850,51 @@ func (m *EventLeaveGroup) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +func (m *EventProposalPruned) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *EventProposalPruned) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *EventProposalPruned) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.TallyResult != nil { + { + size, err := m.TallyResult.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintEvents(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + if m.Status != 0 { + i = encodeVarintEvents(dAtA, i, uint64(m.Status)) + i-- + dAtA[i] = 0x10 + } + if m.ProposalId != 0 { + i = encodeVarintEvents(dAtA, i, uint64(m.ProposalId)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + func encodeVarintEvents(dAtA []byte, offset int, v uint64) int { offset -= sovEvents(v) base := offset @@ -913,6 +1027,25 @@ func (m *EventLeaveGroup) Size() (n int) { return n } +func (m *EventProposalPruned) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.ProposalId != 0 { + n += 1 + sovEvents(uint64(m.ProposalId)) + } + if m.Status != 0 { + n += 1 + sovEvents(uint64(m.Status)) + } + if m.TallyResult != nil { + l = m.TallyResult.Size() + n += 1 + l + sovEvents(uint64(l)) + } + return n +} + func sovEvents(x uint64) (n int) { return (math_bits.Len64(x|1) + 6) / 7 } @@ -1649,6 +1782,130 @@ func (m *EventLeaveGroup) Unmarshal(dAtA []byte) error { } return nil } +func (m *EventProposalPruned) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvents + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: EventProposalPruned: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: EventProposalPruned: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field ProposalId", wireType) + } + m.ProposalId = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvents + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.ProposalId |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Status", wireType) + } + m.Status = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvents + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Status |= ProposalStatus(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field TallyResult", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvents + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthEvents + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthEvents + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.TallyResult == nil { + m.TallyResult = &TallyResult{} + } + if err := m.TallyResult.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipEvents(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthEvents + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func skipEvents(dAtA []byte) (n int, err error) { l := len(dAtA) iNdEx := 0 diff --git a/x/group/keeper/genesis.go b/x/group/keeper/genesis.go index 2e0766ed716e..8043b52acce0 100644 --- a/x/group/keeper/genesis.go +++ b/x/group/keeper/genesis.go @@ -42,7 +42,8 @@ func (k Keeper) InitGenesis(ctx types.Context, cdc codec.JSONCodec, data json.Ra return []abci.ValidatorUpdate{} } -func (k Keeper) ExportGenesis(ctx types.Context, cdc codec.JSONCodec) *group.GenesisState { +// ExportGenesis returns the group module's exported genesis. +func (k Keeper) ExportGenesis(ctx types.Context, _ codec.JSONCodec) *group.GenesisState { genesisState := group.NewGenesisState() var groups []*group.GroupInfo diff --git a/x/group/keeper/grpc_query.go b/x/group/keeper/grpc_query.go index ff26844dde56..616f21133847 100644 --- a/x/group/keeper/grpc_query.go +++ b/x/group/keeper/grpc_query.go @@ -2,6 +2,7 @@ package keeper import ( "context" + "math" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" @@ -346,3 +347,25 @@ func (k Keeper) TallyResult(goCtx context.Context, request *group.QueryTallyResu Tally: tallyResult, }, nil } + +// Groups returns all the groups present in the state. +func (k Keeper) Groups(goCtx context.Context, request *group.QueryGroupsRequest) (*group.QueryGroupsResponse, error) { + ctx := sdk.UnwrapSDKContext(goCtx) + + it, err := k.groupTable.PrefixScan(ctx.KVStore(k.key), 1, math.MaxUint64) + if err != nil { + return nil, err + } + defer it.Close() + + var groups []*group.GroupInfo + pageRes, err := orm.Paginate(it, request.Pagination, &groups) + if err != nil { + return nil, err + } + + return &group.QueryGroupsResponse{ + Groups: groups, + Pagination: pageRes, + }, nil +} diff --git a/x/group/keeper/keeper.go b/x/group/keeper/keeper.go index 210ce6014c58..02bd70d1206e 100644 --- a/x/group/keeper/keeper.go +++ b/x/group/keeper/keeper.go @@ -367,6 +367,15 @@ func (k Keeper) PruneProposals(ctx sdk.Context) error { if err != nil { return err } + // Emit event for proposal finalized with its result + if err := ctx.EventManager().EmitTypedEvent( + &group.EventProposalPruned{ + ProposalId: proposal.Id, + Status: proposal.Status, + TallyResult: &proposal.FinalTallyResult, + }); err != nil { + return err + } } return nil @@ -401,6 +410,14 @@ func (k Keeper) TallyProposalsAtVPEnd(ctx sdk.Context) error { if err := k.pruneVotes(ctx, proposalID); err != nil { return err } + // Emit event for proposal finalized with its result + if err := ctx.EventManager().EmitTypedEvent( + &group.EventProposalPruned{ + ProposalId: proposal.Id, + Status: proposal.Status, + }); err != nil { + return err + } } else if proposal.Status == group.PROPOSAL_STATUS_SUBMITTED { if err := k.doTallyAndUpdate(ctx, &proposal, electorate, policyInfo); err != nil { return sdkerrors.Wrap(err, "doTallyAndUpdate") diff --git a/x/group/keeper/keeper_test.go b/x/group/keeper/keeper_test.go index 56a748018965..e9c9aa9539cc 100644 --- a/x/group/keeper/keeper_test.go +++ b/x/group/keeper/keeper_test.go @@ -9,6 +9,7 @@ import ( "time" "github.com/stretchr/testify/suite" + abci "github.com/tendermint/tendermint/abci/types" tmproto "github.com/tendermint/tendermint/proto/tendermint/types" tmtime "github.com/tendermint/tendermint/types/time" @@ -23,6 +24,8 @@ import ( "github.com/cosmos/cosmos-sdk/x/group/module" ) +var EventProposalPruned = "cosmos.group.v1.EventProposalPruned" + const minExecutionPeriod = 5 * time.Second type TestSuite struct { @@ -1663,6 +1666,8 @@ func (s *TestSuite) TestSubmitProposal() { s.Require().Contains(fromBalances, sdk.NewInt64Coin("test", 9900)) toBalances := s.app.BankKeeper.GetAllBalances(sdkCtx, addr2) s.Require().Contains(toBalances, sdk.NewInt64Coin("test", 100)) + events := sdkCtx.EventManager().ABCIEvents() + s.Require().True(eventTypeFound(events, EventProposalPruned)) }, }, "with try exec, not enough yes votes for proposal to pass": { @@ -1751,6 +1756,7 @@ func (s *TestSuite) TestWithdrawProposal() { proposalId uint64 admin string expErrMsg string + postRun func(sdkCtx sdk.Context) }{ "wrong admin": { preRun: func(sdkCtx sdk.Context) uint64 { @@ -1758,6 +1764,7 @@ func (s *TestSuite) TestWithdrawProposal() { }, admin: addr5.String(), expErrMsg: "unauthorized", + postRun: func(sdkCtx sdk.Context) {}, }, "wrong proposalId": { preRun: func(sdkCtx sdk.Context) uint64 { @@ -1765,6 +1772,7 @@ func (s *TestSuite) TestWithdrawProposal() { }, admin: proposers[0], expErrMsg: "not found", + postRun: func(sdkCtx sdk.Context) {}, }, "happy case with proposer": { preRun: func(sdkCtx sdk.Context) uint64 { @@ -1772,6 +1780,7 @@ func (s *TestSuite) TestWithdrawProposal() { }, proposalId: proposalID, admin: proposers[0], + postRun: func(sdkCtx sdk.Context) {}, }, "already closed proposal": { preRun: func(sdkCtx sdk.Context) uint64 { @@ -1786,6 +1795,7 @@ func (s *TestSuite) TestWithdrawProposal() { proposalId: proposalID, admin: proposers[0], expErrMsg: "cannot withdraw a proposal with the status of PROPOSAL_STATUS_WITHDRAWN", + postRun: func(sdkCtx sdk.Context) {}, }, "happy case with group admin address": { preRun: func(sdkCtx sdk.Context) uint64 { @@ -1793,6 +1803,17 @@ func (s *TestSuite) TestWithdrawProposal() { }, proposalId: proposalID, admin: proposers[0], + postRun: func(sdkCtx sdk.Context) { + resp, err := s.keeper.Proposal(s.ctx, &group.QueryProposalRequest{ProposalId: proposalID}) + s.Require().NoError(err) + vpe := resp.Proposal.VotingPeriodEnd + timeDiff := vpe.Sub(s.sdkCtx.BlockTime()) + ctxVPE := sdkCtx.WithBlockTime(s.sdkCtx.BlockTime().Add(timeDiff).Add(time.Second * 1)) + s.Require().NoError(s.keeper.TallyProposalsAtVPEnd(ctxVPE)) + events := ctxVPE.EventManager().ABCIEvents() + + s.Require().True(eventTypeFound(events, EventProposalPruned)) + }, }, } for msg, spec := range specs { @@ -1815,6 +1836,7 @@ func (s *TestSuite) TestWithdrawProposal() { resp, err := s.keeper.Proposal(s.ctx, &group.QueryProposalRequest{ProposalId: pId}) s.Require().NoError(err) s.Require().Equal(resp.GetProposal().Status, group.PROPOSAL_STATUS_WITHDRAWN) + spec.postRun(s.sdkCtx) }) } } @@ -2316,6 +2338,7 @@ func (s *TestSuite) TestExecProposal() { expBalance bool expFromBalances sdk.Coin expToBalances sdk.Coin + postRun func(sdkCtx sdk.Context) }{ "proposal executed when accepted": { setupProposal: func(ctx context.Context) uint64 { @@ -2328,6 +2351,10 @@ func (s *TestSuite) TestExecProposal() { expBalance: true, expFromBalances: sdk.NewInt64Coin("test", 9900), expToBalances: sdk.NewInt64Coin("test", 100), + postRun: func(sdkCtx sdk.Context) { + events := sdkCtx.EventManager().ABCIEvents() + s.Require().True(eventTypeFound(events, EventProposalPruned)) + }, }, "proposal with multiple messages executed when accepted": { setupProposal: func(ctx context.Context) uint64 { @@ -2340,6 +2367,10 @@ func (s *TestSuite) TestExecProposal() { expBalance: true, expFromBalances: sdk.NewInt64Coin("test", 9800), expToBalances: sdk.NewInt64Coin("test", 200), + postRun: func(sdkCtx sdk.Context) { + events := sdkCtx.EventManager().ABCIEvents() + s.Require().True(eventTypeFound(events, EventProposalPruned)) + }, }, "proposal not executed when rejected": { setupProposal: func(ctx context.Context) uint64 { @@ -2349,6 +2380,7 @@ func (s *TestSuite) TestExecProposal() { srcBlockTime: s.blockTime.Add(minExecutionPeriod), // After min execution period end expProposalStatus: group.PROPOSAL_STATUS_REJECTED, expExecutorResult: group.PROPOSAL_EXECUTOR_RESULT_NOT_RUN, + postRun: func(sdkCtx sdk.Context) {}, }, "open proposal must not fail": { setupProposal: func(ctx context.Context) uint64 { @@ -2356,12 +2388,14 @@ func (s *TestSuite) TestExecProposal() { }, expProposalStatus: group.PROPOSAL_STATUS_SUBMITTED, expExecutorResult: group.PROPOSAL_EXECUTOR_RESULT_NOT_RUN, + postRun: func(sdkCtx sdk.Context) {}, }, "existing proposal required": { setupProposal: func(ctx context.Context) uint64 { return 9999 }, - expErr: true, + expErr: true, + postRun: func(sdkCtx sdk.Context) {}, }, "Decision policy also applied on exactly voting period end": { setupProposal: func(ctx context.Context) uint64 { @@ -2371,6 +2405,7 @@ func (s *TestSuite) TestExecProposal() { srcBlockTime: s.blockTime.Add(time.Second), // Voting period is 1s expProposalStatus: group.PROPOSAL_STATUS_REJECTED, expExecutorResult: group.PROPOSAL_EXECUTOR_RESULT_NOT_RUN, + postRun: func(sdkCtx sdk.Context) {}, }, "Decision policy also applied after voting period end": { setupProposal: func(ctx context.Context) uint64 { @@ -2380,6 +2415,7 @@ func (s *TestSuite) TestExecProposal() { srcBlockTime: s.blockTime.Add(time.Second).Add(time.Millisecond), // Voting period is 1s expProposalStatus: group.PROPOSAL_STATUS_REJECTED, expExecutorResult: group.PROPOSAL_EXECUTOR_RESULT_NOT_RUN, + postRun: func(sdkCtx sdk.Context) {}, }, "exec proposal before MinExecutionPeriod should fail": { setupProposal: func(ctx context.Context) uint64 { @@ -2389,6 +2425,7 @@ func (s *TestSuite) TestExecProposal() { srcBlockTime: s.blockTime.Add(4 * time.Second), // min execution date is 5s later after s.blockTime expProposalStatus: group.PROPOSAL_STATUS_ACCEPTED, expExecutorResult: group.PROPOSAL_EXECUTOR_RESULT_FAILURE, // Because MinExecutionPeriod has not passed + postRun: func(sdkCtx sdk.Context) {}, }, "exec proposal at exactly MinExecutionPeriod should pass": { setupProposal: func(ctx context.Context) uint64 { @@ -2398,6 +2435,10 @@ func (s *TestSuite) TestExecProposal() { srcBlockTime: s.blockTime.Add(5 * time.Second), // min execution date is 5s later after s.blockTime expProposalStatus: group.PROPOSAL_STATUS_ACCEPTED, expExecutorResult: group.PROPOSAL_EXECUTOR_RESULT_SUCCESS, + postRun: func(sdkCtx sdk.Context) { + events := sdkCtx.EventManager().ABCIEvents() + s.Require().True(eventTypeFound(events, EventProposalPruned)) + }, }, "prevent double execution when successful": { setupProposal: func(ctx context.Context) uint64 { @@ -2419,6 +2460,10 @@ func (s *TestSuite) TestExecProposal() { expBalance: true, expFromBalances: sdk.NewInt64Coin("test", 9900), expToBalances: sdk.NewInt64Coin("test", 100), + postRun: func(sdkCtx sdk.Context) { + events := sdkCtx.EventManager().ABCIEvents() + s.Require().True(eventTypeFound(events, EventProposalPruned)) + }, }, "rollback all msg updates on failure": { setupProposal: func(ctx context.Context) uint64 { @@ -2428,6 +2473,7 @@ func (s *TestSuite) TestExecProposal() { srcBlockTime: s.blockTime.Add(minExecutionPeriod), // After min execution period end expProposalStatus: group.PROPOSAL_STATUS_ACCEPTED, expExecutorResult: group.PROPOSAL_EXECUTOR_RESULT_FAILURE, + postRun: func(sdkCtx sdk.Context) {}, }, "executable when failed before": { setupProposal: func(ctx context.Context) uint64 { @@ -2444,6 +2490,10 @@ func (s *TestSuite) TestExecProposal() { srcBlockTime: s.blockTime.Add(minExecutionPeriod), // After min execution period end expProposalStatus: group.PROPOSAL_STATUS_ACCEPTED, expExecutorResult: group.PROPOSAL_EXECUTOR_RESULT_SUCCESS, + postRun: func(sdkCtx sdk.Context) { + events := sdkCtx.EventManager().ABCIEvents() + s.Require().True(eventTypeFound(events, EventProposalPruned)) + }, }, } for msg, spec := range specs { @@ -2487,6 +2537,8 @@ func (s *TestSuite) TestExecProposal() { toBalances := s.app.BankKeeper.GetAllBalances(sdkCtx, addr2) s.Require().Contains(toBalances, spec.expToBalances) } + + spec.postRun(sdkCtx) }) } } @@ -2629,6 +2681,8 @@ func (s *TestSuite) TestExecPrunedProposalsAndVotes() { res, err := s.keeper.VotesByProposal(ctx, &group.QueryVotesByProposalRequest{ProposalId: proposalID}) s.Require().NoError(err) s.Require().Empty(res.GetVotes()) + events := sdkCtx.EventManager().ABCIEvents() + s.Require().True(eventTypeFound(events, EventProposalPruned)) } else { // Check that proposal and votes exists @@ -3191,3 +3245,14 @@ func (s *TestSuite) TestTallyProposalsAtVPEnd_GroupMemberLeaving() { s.Require().NoError(s.app.GroupKeeper.TallyProposalsAtVPEnd(ctx)) s.NotPanics(func() { module.EndBlocker(ctx, s.app.GroupKeeper) }) } + +func eventTypeFound(events []abci.Event, eventType string) bool { + eventTypeFound := false + for _, e := range events { + if e.Type == eventType { + eventTypeFound = true + break + } + } + return eventTypeFound +} diff --git a/x/group/keeper/msg_server.go b/x/group/keeper/msg_server.go index 3947f0adad50..d4ffcdbbcffc 100644 --- a/x/group/keeper/msg_server.go +++ b/x/group/keeper/msg_server.go @@ -702,6 +702,7 @@ func (k Keeper) doTallyAndUpdate(ctx sdk.Context, p *group.Proposal, electorate } else { p.Status = group.PROPOSAL_STATUS_REJECTED } + } return nil @@ -773,6 +774,16 @@ func (k Keeper) Exec(goCtx context.Context, req *group.MsgExec) (*group.MsgExecR if err := k.pruneProposal(ctx, proposal.Id); err != nil { return nil, err } + + // Emit event for proposal finalized with its result + if err := ctx.EventManager().EmitTypedEvent( + &group.EventProposalPruned{ + ProposalId: proposal.Id, + Status: proposal.Status, + TallyResult: &proposal.FinalTallyResult, + }); err != nil { + return nil, err + } } else { store := ctx.KVStore(k.key) if err := k.proposalTable.Update(store, id, &proposal); err != nil { diff --git a/x/group/query.pb.go b/x/group/query.pb.go index 47cfd7fccd98..ec7e0f9a6da0 100644 --- a/x/group/query.pb.go +++ b/x/group/query.pb.go @@ -1380,6 +1380,111 @@ func (m *QueryTallyResultResponse) GetTally() TallyResult { return TallyResult{} } +// QueryGroupsRequest is the Query/Groups request type. +// +// Since: cosmos-sdk 0.47.1 +type QueryGroupsRequest struct { + // pagination defines an optional pagination for the request. + Pagination *query.PageRequest `protobuf:"bytes,2,opt,name=pagination,proto3" json:"pagination,omitempty"` +} + +func (m *QueryGroupsRequest) Reset() { *m = QueryGroupsRequest{} } +func (m *QueryGroupsRequest) String() string { return proto.CompactTextString(m) } +func (*QueryGroupsRequest) ProtoMessage() {} +func (*QueryGroupsRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_0fcf9f1d74302290, []int{26} +} +func (m *QueryGroupsRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryGroupsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryGroupsRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryGroupsRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryGroupsRequest.Merge(m, src) +} +func (m *QueryGroupsRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryGroupsRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryGroupsRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryGroupsRequest proto.InternalMessageInfo + +func (m *QueryGroupsRequest) GetPagination() *query.PageRequest { + if m != nil { + return m.Pagination + } + return nil +} + +// QueryGroupsResponse is the Query/Groups response type. +// +// Since: cosmos-sdk 0.47.1 +type QueryGroupsResponse struct { + // `groups` is all the groups present in state. + Groups []*GroupInfo `protobuf:"bytes,1,rep,name=groups,proto3" json:"groups,omitempty"` + // pagination defines the pagination in the response. + Pagination *query.PageResponse `protobuf:"bytes,2,opt,name=pagination,proto3" json:"pagination,omitempty"` +} + +func (m *QueryGroupsResponse) Reset() { *m = QueryGroupsResponse{} } +func (m *QueryGroupsResponse) String() string { return proto.CompactTextString(m) } +func (*QueryGroupsResponse) ProtoMessage() {} +func (*QueryGroupsResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_0fcf9f1d74302290, []int{27} +} +func (m *QueryGroupsResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryGroupsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryGroupsResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryGroupsResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryGroupsResponse.Merge(m, src) +} +func (m *QueryGroupsResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryGroupsResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryGroupsResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryGroupsResponse proto.InternalMessageInfo + +func (m *QueryGroupsResponse) GetGroups() []*GroupInfo { + if m != nil { + return m.Groups + } + return nil +} + +func (m *QueryGroupsResponse) GetPagination() *query.PageResponse { + if m != nil { + return m.Pagination + } + return nil +} + func init() { proto.RegisterType((*QueryGroupInfoRequest)(nil), "cosmos.group.v1.QueryGroupInfoRequest") proto.RegisterType((*QueryGroupInfoResponse)(nil), "cosmos.group.v1.QueryGroupInfoResponse") @@ -1407,91 +1512,95 @@ func init() { proto.RegisterType((*QueryGroupsByMemberResponse)(nil), "cosmos.group.v1.QueryGroupsByMemberResponse") proto.RegisterType((*QueryTallyResultRequest)(nil), "cosmos.group.v1.QueryTallyResultRequest") proto.RegisterType((*QueryTallyResultResponse)(nil), "cosmos.group.v1.QueryTallyResultResponse") + proto.RegisterType((*QueryGroupsRequest)(nil), "cosmos.group.v1.QueryGroupsRequest") + proto.RegisterType((*QueryGroupsResponse)(nil), "cosmos.group.v1.QueryGroupsResponse") } func init() { proto.RegisterFile("cosmos/group/v1/query.proto", fileDescriptor_0fcf9f1d74302290) } var fileDescriptor_0fcf9f1d74302290 = []byte{ - // 1249 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0x98, 0xcf, 0x6f, 0xdc, 0x44, - 0x14, 0xc7, 0x33, 0x25, 0x69, 0x92, 0x97, 0xb6, 0x11, 0x43, 0x5a, 0x12, 0x37, 0xda, 0x04, 0x03, - 0xf9, 0x1d, 0x3b, 0xbb, 0x49, 0xd3, 0x8a, 0x9f, 0xea, 0x4a, 0x10, 0x72, 0x28, 0x4a, 0x97, 0x88, - 0x03, 0x97, 0xc8, 0x9b, 0x75, 0x8c, 0xc5, 0xae, 0x67, 0xbb, 0x76, 0x22, 0x56, 0xd1, 0x5e, 0x90, - 0xca, 0x01, 0x71, 0x00, 0x8a, 0x50, 0x89, 0x38, 0xf4, 0x80, 0x04, 0x7f, 0x00, 0x08, 0x89, 0x5b, - 0x6f, 0x3d, 0x56, 0x70, 0xe1, 0x84, 0x50, 0xc2, 0x1f, 0x82, 0x3c, 0xf3, 0xbc, 0xeb, 0xdf, 0xeb, - 0x15, 0x2b, 0xc8, 0xa9, 0x5d, 0xfb, 0xbd, 0x79, 0x9f, 0xf9, 0xbe, 0xe7, 0xf1, 0xd7, 0x81, 0xeb, - 0xfb, 0xcc, 0xae, 0x31, 0x5b, 0x35, 0x1a, 0xec, 0xb0, 0xae, 0x1e, 0xe5, 0xd5, 0x7b, 0x87, 0x7a, - 0xa3, 0xa9, 0xd4, 0x1b, 0xcc, 0x61, 0x74, 0x5c, 0xdc, 0x54, 0xf8, 0x4d, 0xe5, 0x28, 0x2f, 0x4d, - 0x18, 0xcc, 0x60, 0xfc, 0x9e, 0xea, 0xfe, 0x4f, 0x84, 0x49, 0xd3, 0x06, 0x63, 0x46, 0x55, 0x57, - 0xb5, 0xba, 0xa9, 0x6a, 0x96, 0xc5, 0x1c, 0xcd, 0x31, 0x99, 0x65, 0xe3, 0xdd, 0x48, 0x05, 0xa7, - 0x59, 0xd7, 0xbd, 0x9b, 0x4b, 0x78, 0xb3, 0xac, 0xd9, 0xba, 0x28, 0xad, 0x1e, 0xe5, 0xcb, 0xba, - 0xa3, 0xe5, 0xd5, 0xba, 0x66, 0x98, 0x16, 0x5f, 0x09, 0x63, 0xa7, 0x44, 0xec, 0x9e, 0xa8, 0x8f, - 0x68, 0xfc, 0x87, 0x5c, 0x80, 0xab, 0x77, 0xdd, 0xe4, 0x2d, 0xb7, 0xc6, 0xb6, 0x75, 0xc0, 0x4a, - 0xfa, 0xbd, 0x43, 0xdd, 0x76, 0xe8, 0x14, 0x8c, 0xf0, 0xba, 0x7b, 0x66, 0x65, 0x92, 0xcc, 0x92, - 0x85, 0xc1, 0xd2, 0x30, 0xff, 0xbd, 0x5d, 0x91, 0xdf, 0x81, 0x6b, 0xe1, 0x1c, 0xbb, 0xce, 0x2c, - 0x5b, 0xa7, 0x0a, 0x0c, 0x9a, 0xd6, 0x01, 0xe3, 0x09, 0x63, 0x05, 0x49, 0x09, 0xa9, 0xa0, 0x74, - 0x32, 0x78, 0x9c, 0x7c, 0x17, 0xae, 0x77, 0x56, 0xda, 0x61, 0x55, 0x73, 0xbf, 0xe9, 0x67, 0x28, - 0xc0, 0xb0, 0x56, 0xa9, 0x34, 0x74, 0xdb, 0xe6, 0x2b, 0x8e, 0x16, 0x27, 0x7f, 0xfb, 0x69, 0x75, - 0x02, 0x17, 0xbd, 0x2d, 0xee, 0xbc, 0xe7, 0x34, 0x4c, 0xcb, 0x28, 0x79, 0x81, 0xf2, 0x2e, 0x4c, - 0xc7, 0x2f, 0x89, 0x88, 0x1b, 0x01, 0xc4, 0xd9, 0x78, 0x44, 0x5f, 0x9e, 0x00, 0x6d, 0xc1, 0x64, - 0x67, 0xd5, 0x3b, 0x7a, 0xad, 0xac, 0x37, 0xec, 0xee, 0x4a, 0xd1, 0xb7, 0x01, 0x3a, 0xcd, 0x98, - 0xbc, 0xc0, 0x4b, 0xce, 0x79, 0x25, 0xdd, 0xce, 0x29, 0x62, 0x68, 0xb0, 0x73, 0xca, 0x8e, 0x66, - 0xe8, 0xb8, 0x6c, 0xc9, 0x97, 0x29, 0x7f, 0x47, 0x60, 0x2a, 0xa6, 0x3e, 0x6e, 0x69, 0x13, 0x86, - 0x6b, 0xe2, 0xd2, 0x24, 0x99, 0x7d, 0x66, 0x61, 0xac, 0x30, 0x1d, 0xbf, 0x2b, 0x91, 0x57, 0xf2, - 0x82, 0xe9, 0x56, 0x0c, 0xdd, 0x7c, 0x57, 0x3a, 0x51, 0x34, 0x80, 0xf7, 0x20, 0x80, 0x67, 0x17, - 0x9b, 0xb7, 0x2b, 0x35, 0xd3, 0xf2, 0xf4, 0x51, 0x60, 0x48, 0x73, 0x7f, 0x77, 0xed, 0xa1, 0x08, - 0xeb, 0x9b, 0x68, 0xdf, 0x12, 0x90, 0xe2, 0xa8, 0x50, 0xb5, 0x02, 0x5c, 0xe4, 0xf2, 0x78, 0xa2, - 0xa5, 0x4d, 0x2b, 0x46, 0xf6, 0x4f, 0xb1, 0xfb, 0x04, 0x66, 0x43, 0x63, 0x6a, 0xea, 0x76, 0x51, - 0xfc, 0xfc, 0x0f, 0x07, 0xeb, 0x67, 0x02, 0x2f, 0xa4, 0x70, 0xa0, 0x54, 0x5b, 0x70, 0x45, 0x80, - 0xd4, 0x31, 0x00, 0x25, 0xeb, 0xfe, 0xf4, 0x5c, 0x36, 0xfc, 0xeb, 0xf6, 0x4f, 0xbf, 0x93, 0x04, - 0xfd, 0xce, 0xc5, 0xe0, 0x25, 0x89, 0x1a, 0x9c, 0xbf, 0xf3, 0x27, 0xea, 0x4d, 0x98, 0xe0, 0xd8, - 0x3b, 0x0d, 0x56, 0x67, 0xb6, 0x56, 0xf5, 0x74, 0x9c, 0x81, 0xb1, 0x3a, 0x5e, 0xea, 0x8c, 0x22, - 0x78, 0x97, 0xb6, 0x2b, 0xf2, 0xbb, 0xf8, 0x12, 0xe9, 0x24, 0xe2, 0x1e, 0x6f, 0xc0, 0x88, 0x17, - 0x86, 0x07, 0xee, 0x54, 0x64, 0x77, 0xed, 0xa4, 0x76, 0xa8, 0xfc, 0x88, 0x80, 0x1c, 0x58, 0xd0, - 0x9b, 0x48, 0x21, 0xc2, 0xbf, 0x78, 0x3d, 0xf4, 0xad, 0xc7, 0x3f, 0x10, 0x78, 0x31, 0x15, 0x11, - 0x15, 0xb8, 0x09, 0xa3, 0xde, 0xb6, 0xbc, 0x06, 0xa7, 0x48, 0xd0, 0x89, 0xed, 0x5f, 0x57, 0x1b, - 0x30, 0xc3, 0x41, 0xdf, 0x67, 0x8e, 0x5e, 0x6c, 0xe3, 0xba, 0xbf, 0x1a, 0x59, 0x1b, 0xec, 0x3e, - 0x49, 0x47, 0x6e, 0x02, 0xe7, 0x48, 0x7d, 0x92, 0x78, 0x98, 0x7c, 0x07, 0x9f, 0xce, 0xd8, 0x9a, - 0xa8, 0xcc, 0x22, 0x0c, 0xba, 0xc1, 0x38, 0x17, 0x57, 0x23, 0xa2, 0xb8, 0xd1, 0x25, 0x1e, 0x22, - 0x7f, 0x4a, 0xd0, 0x27, 0xb8, 0xd7, 0xec, 0x62, 0xcf, 0x03, 0xda, 0xb7, 0xae, 0x7f, 0x4d, 0xd0, - 0x5d, 0x44, 0x40, 0x70, 0x53, 0xcb, 0x42, 0x28, 0xaf, 0xd5, 0x09, 0xbb, 0x12, 0x31, 0xfd, 0x6b, - 0xf1, 0x57, 0x04, 0xed, 0x09, 0x62, 0x05, 0x9a, 0xdb, 0xee, 0x1d, 0xc9, 0xd4, 0xbb, 0xbe, 0x69, - 0xf5, 0xa5, 0x67, 0x0a, 0x82, 0x50, 0xff, 0xab, 0x50, 0x0f, 0xc3, 0x96, 0x00, 0x2d, 0xd1, 0x39, - 0x38, 0x50, 0x4e, 0x88, 0xdf, 0x0b, 0xfb, 0xd0, 0xce, 0x83, 0x5d, 0x79, 0x05, 0x9e, 0xe7, 0x6c, - 0xbb, 0x5a, 0xb5, 0xea, 0x9e, 0x6d, 0x87, 0x55, 0x27, 0xf3, 0xcb, 0x61, 0x17, 0x67, 0x33, 0x90, - 0x8b, 0x9b, 0xba, 0x05, 0x43, 0x8e, 0x7b, 0x19, 0x0f, 0x81, 0xa8, 0x6f, 0xf5, 0x25, 0x15, 0x07, - 0x9f, 0xfc, 0x39, 0x33, 0x50, 0x12, 0x09, 0x85, 0xfb, 0xcf, 0xc2, 0x10, 0x5f, 0x96, 0x7e, 0x4e, - 0x60, 0xb4, 0xbd, 0x75, 0x3a, 0x17, 0x59, 0x22, 0xf6, 0xf3, 0x46, 0x9a, 0xef, 0x1a, 0x27, 0x10, - 0x65, 0xe5, 0x93, 0xdf, 0xff, 0x7e, 0x70, 0x61, 0x81, 0xce, 0xa9, 0xe1, 0xaf, 0x31, 0xf4, 0x66, - 0xd6, 0x01, 0x53, 0x8f, 0x3d, 0x9f, 0xd6, 0xa2, 0xdf, 0x13, 0x18, 0x0f, 0xbd, 0xb0, 0xe9, 0x4a, - 0x4a, 0xb1, 0xc8, 0x57, 0x8f, 0xb4, 0x9a, 0x31, 0x1a, 0x01, 0x37, 0x38, 0xa0, 0x42, 0x57, 0x12, - 0x00, 0xb9, 0xbd, 0x68, 0x22, 0x27, 0x4e, 0x6d, 0x8b, 0x3e, 0x24, 0x70, 0xc9, 0xff, 0x31, 0x41, - 0x17, 0x53, 0xaa, 0x06, 0x3f, 0x78, 0xa4, 0xa5, 0x2c, 0xa1, 0x48, 0x97, 0xe7, 0x74, 0xcb, 0x74, - 0x31, 0x81, 0x0e, 0xbf, 0x45, 0xfc, 0x0a, 0x9e, 0x10, 0xb8, 0x1c, 0xb0, 0xec, 0x34, 0xad, 0x60, - 0xc8, 0xf4, 0x49, 0xcb, 0x99, 0x62, 0x91, 0x6e, 0x8d, 0xd3, 0x2d, 0xd1, 0x85, 0x78, 0x3a, 0x7b, - 0xaf, 0xdc, 0xdc, 0xe3, 0xde, 0xd0, 0x55, 0xae, 0x66, 0x5a, 0x2d, 0xfa, 0x2b, 0x81, 0x89, 0x38, - 0xaf, 0x4c, 0xf3, 0xdd, 0xba, 0x16, 0xf1, 0xf7, 0x52, 0xa1, 0x97, 0x14, 0x24, 0x7e, 0x95, 0x13, - 0xdf, 0xa0, 0xeb, 0x69, 0xdd, 0x36, 0x75, 0x4e, 0x2e, 0x6e, 0xf9, 0x94, 0xfd, 0x25, 0x0a, 0x2f, - 0x04, 0xce, 0x06, 0x1f, 0xd0, 0xb9, 0xd0, 0x4b, 0x0a, 0xc2, 0xdf, 0xe2, 0xf0, 0x05, 0xba, 0x96, - 0x01, 0x3e, 0x28, 0xfb, 0x67, 0x04, 0x46, 0xbc, 0x97, 0x2d, 0x7d, 0x39, 0xbe, 0x74, 0xc8, 0x15, - 0x48, 0x73, 0xdd, 0xc2, 0x90, 0x4a, 0xe5, 0x54, 0x8b, 0x74, 0x3e, 0x42, 0xe5, 0x9d, 0x62, 0xea, - 0xb1, 0xef, 0x88, 0x6b, 0xd1, 0xc7, 0x04, 0xae, 0xc5, 0xdb, 0x3e, 0xba, 0x9e, 0x5e, 0x33, 0xd6, - 0xc7, 0x4a, 0x1b, 0xbd, 0x25, 0x21, 0xf6, 0x6b, 0x1c, 0x7b, 0x93, 0x6e, 0x24, 0x62, 0x77, 0x86, - 0x00, 0x0f, 0x01, 0xdf, 0xf3, 0xff, 0x98, 0xc0, 0x73, 0x31, 0xee, 0x8c, 0xae, 0xc5, 0xb3, 0x24, - 0x9b, 0x47, 0x29, 0xdf, 0x43, 0x06, 0xa2, 0xbf, 0xc5, 0xd1, 0xdf, 0xa4, 0xaf, 0x47, 0xd0, 0xdd, - 0xf7, 0xbd, 0x4b, 0xdd, 0xd6, 0x9b, 0x7b, 0x92, 0xa0, 0xfe, 0xea, 0x31, 0xbf, 0xd8, 0xa2, 0x3f, - 0x12, 0x18, 0x0f, 0x19, 0xb1, 0xa4, 0xa3, 0x36, 0xde, 0x38, 0x26, 0x1d, 0xb5, 0x09, 0xee, 0x2e, - 0x65, 0x7e, 0xb9, 0x4f, 0xf1, 0x83, 0x87, 0x46, 0xe6, 0x1b, 0x02, 0x97, 0xfc, 0x3e, 0x28, 0xe9, - 0xb8, 0x8d, 0x31, 0x70, 0x49, 0xc7, 0x6d, 0x9c, 0xad, 0x4a, 0x99, 0xe5, 0x36, 0x21, 0x2a, 0x8a, - 0x1a, 0x3e, 0x22, 0x70, 0x25, 0xe8, 0x38, 0x68, 0x97, 0x13, 0x34, 0x60, 0x99, 0xa4, 0x95, 0x6c, - 0xc1, 0x88, 0xb7, 0xce, 0xf1, 0x56, 0xe9, 0x72, 0xca, 0x79, 0x2b, 0xde, 0x08, 0xbe, 0x51, 0x3d, - 0x21, 0x30, 0xe6, 0xf3, 0x01, 0x74, 0x21, 0xbe, 0x64, 0xd4, 0x9b, 0x48, 0x8b, 0x19, 0x22, 0x91, - 0x6c, 0x93, 0x93, 0xad, 0x51, 0x25, 0xf9, 0x69, 0x0a, 0x4d, 0x21, 0xf7, 0x21, 0xc5, 0x37, 0x9e, - 0x9c, 0xe6, 0xc8, 0xd3, 0xd3, 0x1c, 0xf9, 0xeb, 0x34, 0x47, 0xbe, 0x38, 0xcb, 0x0d, 0x3c, 0x3d, - 0xcb, 0x0d, 0xfc, 0x71, 0x96, 0x1b, 0xf8, 0xe0, 0x25, 0xc3, 0x74, 0x3e, 0x3c, 0x2c, 0x2b, 0xfb, - 0xac, 0xe6, 0xad, 0x29, 0xfe, 0x59, 0xb5, 0x2b, 0x1f, 0xa9, 0x1f, 0x8b, 0x02, 0xe5, 0x8b, 0xfc, - 0xcf, 0xb0, 0xeb, 0xff, 0x04, 0x00, 0x00, 0xff, 0xff, 0x11, 0xfe, 0x04, 0xa9, 0x4e, 0x16, 0x00, - 0x00, + // 1292 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0x98, 0x4b, 0x6f, 0x1b, 0x55, + 0x14, 0xc7, 0x73, 0x4b, 0x9e, 0x27, 0x6d, 0x23, 0x6e, 0xd3, 0x36, 0x99, 0x46, 0x4e, 0x98, 0x96, + 0xbc, 0x33, 0x13, 0x3b, 0x69, 0x5a, 0xf1, 0x54, 0x2d, 0x41, 0xc8, 0xa2, 0x28, 0x35, 0x11, 0x0b, + 0x84, 0x14, 0x8d, 0xe3, 0x89, 0x19, 0x61, 0xcf, 0xb8, 0x9e, 0x49, 0x84, 0x15, 0x79, 0x83, 0x04, + 0x0b, 0xc4, 0x02, 0x5a, 0x84, 0x4a, 0xc4, 0xa2, 0x0b, 0x24, 0xf8, 0x00, 0x20, 0x24, 0x76, 0xdd, + 0x75, 0x59, 0xc1, 0x86, 0x15, 0x42, 0x09, 0xdf, 0x82, 0x0d, 0x9a, 0x7b, 0xcf, 0xb5, 0xe7, 0xed, + 0x89, 0xb0, 0xc0, 0xab, 0x76, 0x66, 0xce, 0xb9, 0xe7, 0x37, 0xff, 0x73, 0xe6, 0xfa, 0x7f, 0x03, + 0xd7, 0xf6, 0x2c, 0xbb, 0x6a, 0xd9, 0x6a, 0xb9, 0x6e, 0x1d, 0xd4, 0xd4, 0xc3, 0xac, 0x7a, 0xff, + 0x40, 0xaf, 0x37, 0x94, 0x5a, 0xdd, 0x72, 0x2c, 0x3a, 0xc6, 0x1f, 0x2a, 0xec, 0xa1, 0x72, 0x98, + 0x95, 0xc6, 0xcb, 0x56, 0xd9, 0x62, 0xcf, 0x54, 0xf7, 0x7f, 0x3c, 0x4c, 0x9a, 0x2a, 0x5b, 0x56, + 0xb9, 0xa2, 0xab, 0x5a, 0xcd, 0x50, 0x35, 0xd3, 0xb4, 0x1c, 0xcd, 0x31, 0x2c, 0xd3, 0xc6, 0xa7, + 0xa1, 0x0a, 0x4e, 0xa3, 0xa6, 0x8b, 0x87, 0x8b, 0xf8, 0xb0, 0xa8, 0xd9, 0x3a, 0x2f, 0xad, 0x1e, + 0x66, 0x8b, 0xba, 0xa3, 0x65, 0xd5, 0x9a, 0x56, 0x36, 0x4c, 0xb6, 0x12, 0xc6, 0x4e, 0xf2, 0xd8, + 0x5d, 0x5e, 0x1f, 0xd1, 0xd8, 0x85, 0x9c, 0x83, 0xcb, 0xf7, 0xdc, 0xe4, 0x4d, 0xb7, 0xc6, 0x96, + 0xb9, 0x6f, 0x15, 0xf4, 0xfb, 0x07, 0xba, 0xed, 0xd0, 0x49, 0x18, 0x66, 0x75, 0x77, 0x8d, 0xd2, + 0x04, 0x99, 0x21, 0xf3, 0xfd, 0x85, 0x21, 0x76, 0xbd, 0x55, 0x92, 0xdf, 0x82, 0x2b, 0xc1, 0x1c, + 0xbb, 0x66, 0x99, 0xb6, 0x4e, 0x15, 0xe8, 0x37, 0xcc, 0x7d, 0x8b, 0x25, 0x8c, 0xe6, 0x24, 0x25, + 0xa0, 0x82, 0xd2, 0xce, 0x60, 0x71, 0xf2, 0x3d, 0xb8, 0xd6, 0x5e, 0x69, 0xdb, 0xaa, 0x18, 0x7b, + 0x0d, 0x2f, 0x43, 0x0e, 0x86, 0xb4, 0x52, 0xa9, 0xae, 0xdb, 0x36, 0x5b, 0x71, 0x24, 0x3f, 0xf1, + 0xeb, 0x8f, 0x2b, 0xe3, 0xb8, 0xe8, 0x1d, 0xfe, 0xe4, 0x1d, 0xa7, 0x6e, 0x98, 0xe5, 0x82, 0x08, + 0x94, 0x77, 0x60, 0x2a, 0x7a, 0x49, 0x44, 0x5c, 0xf7, 0x21, 0xce, 0x44, 0x23, 0x7a, 0xf2, 0x38, + 0x68, 0x13, 0x26, 0xda, 0xab, 0xde, 0xd5, 0xab, 0x45, 0xbd, 0x6e, 0x77, 0x56, 0x8a, 0xbe, 0x09, + 0xd0, 0x6e, 0xc6, 0xc4, 0x39, 0x56, 0x72, 0x56, 0x94, 0x74, 0x3b, 0xa7, 0xf0, 0xa1, 0xc1, 0xce, + 0x29, 0xdb, 0x5a, 0x59, 0xc7, 0x65, 0x0b, 0x9e, 0x4c, 0xf9, 0x5b, 0x02, 0x93, 0x11, 0xf5, 0xf1, + 0x95, 0x36, 0x60, 0xa8, 0xca, 0x6f, 0x4d, 0x90, 0x99, 0xe7, 0xe6, 0x47, 0x73, 0x53, 0xd1, 0x6f, + 0xc5, 0xf3, 0x0a, 0x22, 0x98, 0x6e, 0x46, 0xd0, 0xcd, 0x75, 0xa4, 0xe3, 0x45, 0x7d, 0x78, 0x0f, + 0x7d, 0x78, 0x76, 0xbe, 0x71, 0xa7, 0x54, 0x35, 0x4c, 0xa1, 0x8f, 0x02, 0x03, 0x9a, 0x7b, 0xdd, + 0xb1, 0x87, 0x3c, 0xac, 0x6b, 0xa2, 0x7d, 0x43, 0x40, 0x8a, 0xa2, 0x42, 0xd5, 0x72, 0x30, 0xc8, + 0xe4, 0x11, 0xa2, 0x25, 0x4d, 0x2b, 0x46, 0x76, 0x4f, 0xb1, 0x4f, 0x08, 0xcc, 0x04, 0xc6, 0xd4, + 0xd0, 0xed, 0x3c, 0xbf, 0xfc, 0x0f, 0x07, 0xeb, 0x27, 0x02, 0x2f, 0x24, 0x70, 0xa0, 0x54, 0x9b, + 0x70, 0x91, 0x83, 0xd4, 0x30, 0x00, 0x25, 0xeb, 0xfc, 0xf5, 0x5c, 0x28, 0x7b, 0xd7, 0xed, 0x9e, + 0x7e, 0xc7, 0x31, 0xfa, 0xf5, 0xc4, 0xe0, 0xc5, 0x89, 0xea, 0x9f, 0xbf, 0xde, 0x13, 0xf5, 0x16, + 0x8c, 0x33, 0xec, 0xed, 0xba, 0x55, 0xb3, 0x6c, 0xad, 0x22, 0x74, 0x9c, 0x86, 0xd1, 0x1a, 0xde, + 0x6a, 0x8f, 0x22, 0x88, 0x5b, 0x5b, 0x25, 0xf9, 0x6d, 0xfc, 0x11, 0x69, 0x27, 0xe2, 0x3b, 0xde, + 0x84, 0x61, 0x11, 0x86, 0x1b, 0xee, 0x64, 0xe8, 0xed, 0x5a, 0x49, 0xad, 0x50, 0xf9, 0x31, 0x01, + 0xd9, 0xb7, 0xa0, 0x98, 0x48, 0x2e, 0xc2, 0xbf, 0xf8, 0x79, 0xe8, 0x5a, 0x8f, 0xbf, 0x27, 0x70, + 0x3d, 0x11, 0x11, 0x15, 0xb8, 0x05, 0x23, 0xe2, 0xb5, 0x44, 0x83, 0x13, 0x24, 0x68, 0xc7, 0x76, + 0xaf, 0xab, 0x75, 0x98, 0x66, 0xa0, 0xef, 0x5a, 0x8e, 0x9e, 0x6f, 0xe1, 0xba, 0x57, 0xf5, 0xb4, + 0x0d, 0x76, 0xbf, 0xa4, 0x43, 0x37, 0x81, 0x71, 0x24, 0x7e, 0x49, 0x2c, 0x4c, 0xbe, 0x8b, 0x5f, + 0x67, 0x64, 0x4d, 0x54, 0x66, 0x01, 0xfa, 0xdd, 0x60, 0x9c, 0x8b, 0xcb, 0x21, 0x51, 0xdc, 0xe8, + 0x02, 0x0b, 0x91, 0x3f, 0x25, 0xe8, 0x13, 0xdc, 0x7b, 0x76, 0xfe, 0xcc, 0x03, 0xda, 0xb5, 0xae, + 0x7f, 0x45, 0xd0, 0x5d, 0x84, 0x40, 0xf0, 0xa5, 0x96, 0xb8, 0x50, 0xa2, 0xd5, 0x31, 0x6f, 0xc5, + 0x63, 0xba, 0xd7, 0xe2, 0x07, 0x04, 0xed, 0x09, 0x62, 0xf9, 0x9a, 0xdb, 0xea, 0x1d, 0x49, 0xd5, + 0xbb, 0xae, 0x69, 0xf5, 0xa5, 0x30, 0x05, 0x7e, 0xa8, 0xff, 0x55, 0xa8, 0x47, 0x41, 0x4b, 0x80, + 0x96, 0xa8, 0x07, 0x36, 0x94, 0x63, 0xe2, 0xf5, 0xc2, 0x1e, 0xb4, 0x5e, 0xb0, 0x2b, 0x2f, 0xc1, + 0x55, 0xc6, 0xb6, 0xa3, 0x55, 0x2a, 0xee, 0xde, 0x76, 0x50, 0x71, 0x52, 0xff, 0x38, 0xec, 0xe0, + 0x6c, 0xfa, 0x72, 0xf1, 0xa5, 0x6e, 0xc3, 0x80, 0xe3, 0xde, 0xc6, 0x4d, 0x20, 0xec, 0x5b, 0x3d, + 0x49, 0xf9, 0xfe, 0xa7, 0x7f, 0x4c, 0xf7, 0x15, 0x78, 0x82, 0xfc, 0x3e, 0x50, 0x8f, 0x5a, 0x02, + 0xa6, 0x5b, 0xcd, 0x78, 0x40, 0xe0, 0x92, 0x6f, 0xf9, 0x1e, 0x68, 0x42, 0xee, 0xef, 0xe7, 0x61, + 0x80, 0x41, 0xd1, 0xcf, 0x09, 0x8c, 0xb4, 0x0a, 0xd1, 0xd9, 0x10, 0x44, 0xe4, 0x89, 0x4e, 0x9a, + 0xeb, 0x18, 0xc7, 0x8b, 0xca, 0xca, 0xc7, 0xbf, 0xfd, 0xf5, 0xf0, 0xdc, 0x3c, 0x9d, 0x55, 0x83, + 0x07, 0x50, 0xb4, 0xa3, 0xe6, 0xbe, 0xa5, 0x1e, 0x09, 0x6b, 0xda, 0xa4, 0xdf, 0x11, 0x18, 0x0b, + 0x78, 0x14, 0xba, 0x9c, 0x50, 0x2c, 0x74, 0xd0, 0x93, 0x56, 0x52, 0x46, 0x23, 0xe0, 0x3a, 0x03, + 0x54, 0xe8, 0x72, 0x0c, 0x20, 0x73, 0x54, 0x0d, 0xe4, 0xc4, 0x0f, 0xb5, 0x49, 0x1f, 0x11, 0x38, + 0xef, 0x3d, 0x3f, 0xd1, 0x85, 0x84, 0xaa, 0xfe, 0x33, 0x9e, 0xb4, 0x98, 0x26, 0x14, 0xe9, 0xb2, + 0x8c, 0x6e, 0x89, 0x2e, 0xc4, 0xd0, 0xe1, 0xf1, 0xcb, 0xab, 0xe0, 0x31, 0x81, 0x0b, 0xbe, 0x53, + 0x0a, 0x4d, 0x2a, 0x18, 0xf0, 0xb9, 0xd2, 0x52, 0xaa, 0x58, 0xa4, 0x5b, 0x65, 0x74, 0x8b, 0x74, + 0x3e, 0x9a, 0xce, 0xde, 0x2d, 0x36, 0x76, 0x99, 0x1d, 0x76, 0x95, 0xab, 0x1a, 0x66, 0x93, 0xfe, + 0x42, 0x60, 0x3c, 0xea, 0x78, 0x40, 0xb3, 0x9d, 0xba, 0x16, 0x3a, 0xd2, 0x48, 0xb9, 0xb3, 0xa4, + 0x20, 0xf1, 0xcb, 0x8c, 0xf8, 0x26, 0x5d, 0x4b, 0xea, 0xb6, 0xa1, 0x33, 0x72, 0xfe, 0xc8, 0xa3, + 0xec, 0xcf, 0x61, 0x78, 0x2e, 0x70, 0x3a, 0x78, 0x9f, 0xce, 0xb9, 0xb3, 0xa4, 0x20, 0xfc, 0x6d, + 0x06, 0x9f, 0xa3, 0xab, 0x29, 0xe0, 0xfd, 0xb2, 0x7f, 0x46, 0x60, 0x58, 0xf8, 0x0b, 0xfa, 0x62, + 0x74, 0xe9, 0x80, 0x11, 0x92, 0x66, 0x3b, 0x85, 0x21, 0x95, 0xca, 0xa8, 0x16, 0xe8, 0x5c, 0x88, + 0x4a, 0x6c, 0xdc, 0xea, 0x91, 0x67, 0x57, 0x6f, 0xd2, 0x27, 0x04, 0xae, 0x44, 0x3b, 0x5d, 0xba, + 0x96, 0x5c, 0x33, 0xd2, 0xba, 0x4b, 0xeb, 0x67, 0x4b, 0x42, 0xec, 0x57, 0x18, 0xf6, 0x06, 0x5d, + 0x8f, 0xc5, 0x6e, 0x0f, 0x01, 0x6e, 0x02, 0x9e, 0xef, 0xff, 0x09, 0x81, 0x4b, 0x11, 0x86, 0x94, + 0xae, 0x46, 0xb3, 0xc4, 0xfb, 0x65, 0x29, 0x7b, 0x86, 0x0c, 0x44, 0x7f, 0x83, 0xa1, 0xbf, 0x4e, + 0x5f, 0x0d, 0xa1, 0xbb, 0x16, 0xc7, 0xa5, 0x6e, 0xe9, 0xcd, 0x6c, 0x98, 0x5f, 0x7f, 0xf5, 0x88, + 0xdd, 0x6c, 0xd2, 0x1f, 0x08, 0x8c, 0x05, 0xbc, 0x67, 0xdc, 0x56, 0x1b, 0xed, 0x95, 0xe3, 0xb6, + 0xda, 0x18, 0x43, 0x9b, 0x30, 0xbf, 0xcc, 0x9a, 0x79, 0xc1, 0x03, 0x23, 0xf3, 0x35, 0x81, 0xf3, + 0x5e, 0xeb, 0x17, 0xb7, 0xdd, 0x46, 0x78, 0xd6, 0xb8, 0xed, 0x36, 0xca, 0x49, 0x26, 0xcc, 0x72, + 0x8b, 0x10, 0x15, 0x45, 0x0d, 0x1f, 0x13, 0xb8, 0xe8, 0x37, 0x59, 0xb4, 0xc3, 0x0e, 0xea, 0x73, + 0x89, 0xd2, 0x72, 0xba, 0x60, 0xc4, 0x5b, 0x63, 0x78, 0x2b, 0x74, 0x29, 0x61, 0xbf, 0xe5, 0xbf, + 0x08, 0x9e, 0x51, 0x3d, 0x26, 0x30, 0xea, 0xb1, 0x3e, 0x74, 0x3e, 0xba, 0x64, 0xd8, 0x8e, 0x49, + 0x0b, 0x29, 0x22, 0x91, 0x6c, 0x83, 0x91, 0xad, 0x52, 0x25, 0xfe, 0x6b, 0x0a, 0x4c, 0x21, 0xb3, + 0x5e, 0xd4, 0x81, 0x41, 0xfe, 0xae, 0xf4, 0x7a, 0x92, 0x12, 0x82, 0xe8, 0x46, 0x72, 0x10, 0xc2, + 0x4c, 0x33, 0x98, 0x49, 0x7a, 0x35, 0x46, 0xa6, 0xfc, 0x6b, 0x4f, 0x4f, 0x32, 0xe4, 0xd9, 0x49, + 0x86, 0xfc, 0x79, 0x92, 0x21, 0x5f, 0x9c, 0x66, 0xfa, 0x9e, 0x9d, 0x66, 0xfa, 0x7e, 0x3f, 0xcd, + 0xf4, 0xbd, 0x77, 0xa3, 0x6c, 0x38, 0x1f, 0x1c, 0x14, 0x95, 0x3d, 0xab, 0x2a, 0x92, 0xf9, 0x3f, + 0x2b, 0x76, 0xe9, 0x43, 0xf5, 0x23, 0xbe, 0x40, 0x71, 0x90, 0xfd, 0xbd, 0x7b, 0xed, 0x9f, 0x00, + 0x00, 0x00, 0xff, 0xff, 0x1c, 0xce, 0x79, 0xa7, 0xb7, 0x17, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -1536,6 +1645,10 @@ type QueryClient interface { // then it simply returns the `final_tally_result` state stored in the // proposal itself. TallyResult(ctx context.Context, in *QueryTallyResultRequest, opts ...grpc.CallOption) (*QueryTallyResultResponse, error) + // Groups queries all groups in state. + // + // Since: cosmos-sdk 0.47.1 + Groups(ctx context.Context, in *QueryGroupsRequest, opts ...grpc.CallOption) (*QueryGroupsResponse, error) } type queryClient struct { @@ -1663,6 +1776,15 @@ func (c *queryClient) TallyResult(ctx context.Context, in *QueryTallyResultReque return out, nil } +func (c *queryClient) Groups(ctx context.Context, in *QueryGroupsRequest, opts ...grpc.CallOption) (*QueryGroupsResponse, error) { + out := new(QueryGroupsResponse) + err := c.cc.Invoke(ctx, "/cosmos.group.v1.Query/Groups", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // QueryServer is the server API for Query service. type QueryServer interface { // GroupInfo queries group info based on group id. @@ -1695,6 +1817,10 @@ type QueryServer interface { // then it simply returns the `final_tally_result` state stored in the // proposal itself. TallyResult(context.Context, *QueryTallyResultRequest) (*QueryTallyResultResponse, error) + // Groups queries all groups in state. + // + // Since: cosmos-sdk 0.47.1 + Groups(context.Context, *QueryGroupsRequest) (*QueryGroupsResponse, error) } // UnimplementedQueryServer can be embedded to have forward compatible implementations. @@ -1740,6 +1866,9 @@ func (*UnimplementedQueryServer) GroupsByMember(ctx context.Context, req *QueryG func (*UnimplementedQueryServer) TallyResult(ctx context.Context, req *QueryTallyResultRequest) (*QueryTallyResultResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method TallyResult not implemented") } +func (*UnimplementedQueryServer) Groups(ctx context.Context, req *QueryGroupsRequest) (*QueryGroupsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Groups not implemented") +} func RegisterQueryServer(s grpc1.Server, srv QueryServer) { s.RegisterService(&_Query_serviceDesc, srv) @@ -1979,6 +2108,24 @@ func _Query_TallyResult_Handler(srv interface{}, ctx context.Context, dec func(i return interceptor(ctx, in, info, handler) } +func _Query_Groups_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryGroupsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).Groups(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cosmos.group.v1.Query/Groups", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).Groups(ctx, req.(*QueryGroupsRequest)) + } + return interceptor(ctx, in, info, handler) +} + var _Query_serviceDesc = grpc.ServiceDesc{ ServiceName: "cosmos.group.v1.Query", HandlerType: (*QueryServer)(nil), @@ -2035,6 +2182,10 @@ var _Query_serviceDesc = grpc.ServiceDesc{ MethodName: "TallyResult", Handler: _Query_TallyResult_Handler, }, + { + MethodName: "Groups", + Handler: _Query_Groups_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "cosmos/group/v1/query.proto", @@ -3084,6 +3235,90 @@ func (m *QueryTallyResultResponse) MarshalToSizedBuffer(dAtA []byte) (int, error return len(dAtA) - i, nil } +func (m *QueryGroupsRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QueryGroupsRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryGroupsRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Pagination != nil { + { + size, err := m.Pagination.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + return len(dAtA) - i, nil +} + +func (m *QueryGroupsResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QueryGroupsResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryGroupsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Pagination != nil { + { + size, err := m.Pagination.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + if len(m.Groups) > 0 { + for iNdEx := len(m.Groups) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Groups[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + func encodeVarintQuery(dAtA []byte, offset int, v uint64) int { offset -= sovQuery(v) base := offset @@ -3508,6 +3743,38 @@ func (m *QueryTallyResultResponse) Size() (n int) { return n } +func (m *QueryGroupsRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Pagination != nil { + l = m.Pagination.Size() + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryGroupsResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.Groups) > 0 { + for _, e := range m.Groups { + l = e.Size() + n += 1 + l + sovQuery(uint64(l)) + } + } + if m.Pagination != nil { + l = m.Pagination.Size() + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + func sovQuery(x uint64) (n int) { return (math_bits.Len64(x|1) + 6) / 7 } @@ -6196,6 +6463,212 @@ func (m *QueryTallyResultResponse) Unmarshal(dAtA []byte) error { } return nil } +func (m *QueryGroupsRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryGroupsRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryGroupsRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Pagination", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Pagination == nil { + m.Pagination = &query.PageRequest{} + } + if err := m.Pagination.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryGroupsResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryGroupsResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryGroupsResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Groups", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Groups = append(m.Groups, &GroupInfo{}) + if err := m.Groups[len(m.Groups)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Pagination", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Pagination == nil { + m.Pagination = &query.PageResponse{} + } + if err := m.Pagination.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func skipQuery(dAtA []byte) (n int, err error) { l := len(dAtA) iNdEx := 0 diff --git a/x/group/query.pb.gw.go b/x/group/query.pb.gw.go index d9f8b8c588b0..a0a30e91c3a6 100644 --- a/x/group/query.pb.gw.go +++ b/x/group/query.pb.gw.go @@ -901,6 +901,42 @@ func local_request_Query_TallyResult_0(ctx context.Context, marshaler runtime.Ma } +var ( + filter_Query_Groups_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} +) + +func request_Query_Groups_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryGroupsRequest + var metadata runtime.ServerMetadata + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_Groups_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := client.Groups(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_Groups_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryGroupsRequest + var metadata runtime.ServerMetadata + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_Groups_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.Groups(ctx, &protoReq) + return msg, metadata, err + +} + // RegisterQueryHandlerServer registers the http handlers for service Query to "mux". // UnaryRPC :call QueryServer directly. // StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. @@ -1206,6 +1242,29 @@ func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, serv }) + mux.Handle("GET", pattern_Query_Groups_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_Groups_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_Groups_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + return nil } @@ -1507,6 +1566,26 @@ func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, clie }) + mux.Handle("GET", pattern_Query_Groups_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_Query_Groups_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_Groups_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + return nil } @@ -1536,6 +1615,8 @@ var ( pattern_Query_GroupsByMember_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"cosmos", "group", "v1", "groups_by_member", "address"}, "", runtime.AssumeColonVerbOpt(false))) pattern_Query_TallyResult_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4, 2, 5}, []string{"cosmos", "group", "v1", "proposals", "proposal_id", "tally"}, "", runtime.AssumeColonVerbOpt(false))) + + pattern_Query_Groups_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"cosmos", "group", "v1", "groups"}, "", runtime.AssumeColonVerbOpt(false))) ) var ( @@ -1564,4 +1645,6 @@ var ( forward_Query_GroupsByMember_0 = runtime.ForwardResponseMessage forward_Query_TallyResult_0 = runtime.ForwardResponseMessage + + forward_Query_Groups_0 = runtime.ForwardResponseMessage ) diff --git a/x/group/simulation/genesis.go b/x/group/simulation/genesis.go index 7f30a4fc7303..66b471fa5e47 100644 --- a/x/group/simulation/genesis.go +++ b/x/group/simulation/genesis.go @@ -21,6 +21,16 @@ const ( GroupVote = "group-vote" ) +func checkAccExists(acc sdk.AccAddress, g []*group.GroupMember, lastIndex int) bool { + s := acc.String() + for i := 0; i < lastIndex; i++ { + if g[i].Member.Address == s { + return true + } + } + return false +} + func getGroups(r *rand.Rand, accounts []simtypes.Account) []*group.GroupInfo { groups := make([]*group.GroupInfo, 3) for i := 0; i < 3; i++ { @@ -40,6 +50,9 @@ func getGroupMembers(r *rand.Rand, accounts []simtypes.Account) []*group.GroupMe groupMembers := make([]*group.GroupMember, 3) for i := 0; i < 3; i++ { acc, _ := simtypes.RandomAcc(r, accounts) + for checkAccExists(acc.Address, groupMembers, i) { + acc, _ = simtypes.RandomAcc(r, accounts) + } groupMembers[i] = &group.GroupMember{ GroupId: uint64(i + 1), Member: &group.Member{ @@ -147,6 +160,11 @@ func getVoteOption(index int) group.VoteOption { // RandomizedGenState generates a random GenesisState for the group module. func RandomizedGenState(simState *module.SimulationState) { + // The test requires we have at least 3 accounts. + if len(simState.Accounts) < 3 { + return + } + // groups var groups []*group.GroupInfo simState.AppParams.GetOrGenerate( diff --git a/x/group/spec/04_events.md b/x/group/spec/04_events.md index ca4e2fdf20bb..1f064009d7bc 100644 --- a/x/group/spec/04_events.md +++ b/x/group/spec/04_events.md @@ -70,3 +70,12 @@ The group module emits the following events: | message | action | /cosmos.group.v1.Msg/LeaveGroup | | cosmos.group.v1.EventLeaveGroup | proposal_id | {proposalId} | | cosmos.group.v1.EventLeaveGroup | address | {address} | + +### EventProposalPruned + +| Type | Attribute Key | Attribute Value | +|-------------------------------------|---------------|---------------------------------| +| message | action | /cosmos.group.v1.Msg/LeaveGroup | +| cosmos.group.v1.EventProposalPruned | proposal_id | {proposalId} | +| cosmos.group.v1.EventProposalPruned | status | {ProposalStatus} | +| cosmos.group.v1.EventProposalPruned | tally_result | {TallyResult} | \ No newline at end of file