diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 3b3fee315085..308c61887003 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -29,6 +29,7 @@ /server/v2/stf/ @testinginprod @kocubinski @cosmos/sdk-core-dev /server/v2/appmanager/ @testinginprod @facundomedica @cosmos/sdk-core-dev /server/v2/cometbft/ @facundomedica @sontrinh16 @cosmos/sdk-core-dev +/simsx @alpe @facundomedica @kocubinski @cosmos/sdk-core-dev /simapp/ @facundomedica @julienrbrt @cosmos/sdk-core-dev /simapp/v2/ @kocubinski @julienrbrt @cosmos/sdk-core-dev /store/ @cool-develope @kocubinski @cosmos/sdk-core-dev @@ -37,11 +38,13 @@ /tools/hubl @julienrbrt @JulianToledano @cosmos/sdk-core-dev /tools/cosmovisor @julienrbrt @facundomedica @cosmos/sdk-core-dev /tools/confix @julienrbrt @akhilkumarpilli @cosmos/sdk-core-dev +/tests/integration/aminojson @kocubinski @cosmos/sdk-core-dev # x modules /x/accounts/ @testinginprod @sontrinh16 @cosmos/sdk-core-dev /x/auth/ @facundomedica @testinginprod @aaronc @cosmos/sdk-core-dev +/x/auth/tx/config @julienrbrt @akhilkumarpilli @kocubinski @cosmos/sdk-core-dev /x/authz/ @akhilkumarpilli @raynaudoe @cosmos/sdk-core-dev /x/bank/ @julienrbrt @sontrinh16 @cosmos/sdk-core-dev /x/bank/v2 @julienrbrt @hieuvubk @akhilkumarpilli @cosmos/sdk-core-dev @@ -63,6 +66,7 @@ /x/staking/ @facundomedica @testinginprod @JulianToledano @ziscky @cosmos/sdk-core-dev /x/tx/ @kocubinski @testinginprod @aaronc @cosmos/sdk-core-dev /x/upgrade/ @facundomedica @cool-develope @akhilkumarpilli @lucaslopezf @cosmos/sdk-core-dev +/x/validate @julienrbrt @akhilkumarpilli @kocubinski @cosmos/sdk-core-dev # go mods diff --git a/.github/ISSUE_TEMPLATE/qa.md b/.github/ISSUE_TEMPLATE/qa.md index 6b0ef14807fe..c45a80ddb757 100644 --- a/.github/ISSUE_TEMPLATE/qa.md +++ b/.github/ISSUE_TEMPLATE/qa.md @@ -25,18 +25,20 @@ v without deliberation * [ ] Audit x/auth * [ ] Audit x/authz * [ ] Audit x/bank + * [ ] Audit x/bank/v2 * [ ] Audit x/circuit * [ ] Audit x/consensus * [ ] Audit x/crisis * [ ] Audit x/distribution * [ ] Audit x/evidence + * [ ] Audit x/epochs * [ ] Audit x/feegrant * [ ] Audit x/genutil * [ ] Audit x/gov * [ ] Audit x/group * [ ] Audit x/mint * [ ] Audit x/nft - * [ ] Audit x/simulation + * [ ] Audit x/protocolpool * [ ] Audit x/slashing * [ ] Audit x/staking * [ ] Audit x/tx diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 86fe6e1b2924..82413815cb76 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -187,6 +187,15 @@ updates: labels: - "A:automerge" - dependencies + - package-ecosystem: gomod + directory: "x/accounts/defaults/base" + schedule: + interval: weekly + day: wednesday + time: "02:45" + labels: + - "A:automerge" + - dependencies - package-ecosystem: gomod directory: "x/accounts/defaults/multisig" schedule: diff --git a/.github/pr_labeler.yml b/.github/pr_labeler.yml index 1b850dedc0a9..b3a4ddfbe37b 100644 --- a/.github/pr_labeler.yml +++ b/.github/pr_labeler.yml @@ -10,8 +10,10 @@ "C:Keys": - client/keys/**/* "C:Simulations": + - types/simulation/**/* - x/simulation/**/* - x/*/simulation/**/* + - simsx/**/* "C:Store": - store/**/* "C:collections": @@ -28,6 +30,8 @@ - indexer/postgres/**/* "C:x/accounts": - x/accounts/**/* +"C:x/accounts/base": + - x/accounts/defaults/base/**/* "C:x/accounts/multisig": - x/accounts/defaults/multisig/**/* "C:x/accounts/lockup": @@ -76,6 +80,8 @@ - x/upgrade/**/* "C:x/epochs": - x/epochs/**/* +"C:x/validate": + - x/validate/**/* "C:server/v2": - server/v2/**/* "C:server/v2 stf": diff --git a/.github/workflows/auto-assign-prs.yml b/.github/workflows/auto-assign-prs.yml new file mode 100644 index 000000000000..c7bbd8c5dbe7 --- /dev/null +++ b/.github/workflows/auto-assign-prs.yml @@ -0,0 +1,60 @@ +name: Auto Assign Reviewers + +on: + pull_request: + types: [opened, edited, review_requested] + +jobs: + assign-reviewers: + runs-on: ubuntu-latest + + steps: + - name: Check out the repository + uses: actions/checkout@v4 + + - name: Assign reviewers as assignees + uses: actions/github-script@v7 + with: + github-token: ${{ secrets.PRBOT_PAT }} + script: | + const { owner, repo } = context.repo; + + async function getCurrentPR() { + if (context.payload.pull_request) { + return context.payload.pull_request; + } + + const allPRs = await github.rest.pulls.list({ + owner, + repo, + state: 'open', + }); + + return allPRs.data.find(pr => pr.head.sha === context.sha); + } + + const pr = await getCurrentPR(); + if (!pr) { + console.log('No matching PR found.'); + return; + } + + console.log(`Processing PR #${pr.number}`); + + const reviewers = pr.requested_reviewers.map(reviewer => reviewer.login); + + if (reviewers.length === 0) { + console.log('No reviewers found for this PR.'); + return; + } + + console.log(`Current reviewers: ${reviewers.join(', ')}`); + + await github.rest.issues.addAssignees({ + owner, + repo, + issue_number: pr.number, + assignees: reviewers, + }); + + console.log(`Assigned ${reviewers.join(', ')} as assignees to PR #${pr.number}`); diff --git a/.github/workflows/dependabot-update-all.yml b/.github/workflows/dependabot-update-all.yml index 01e1ecc4eb4a..fa649a7f6316 100644 --- a/.github/workflows/dependabot-update-all.yml +++ b/.github/workflows/dependabot-update-all.yml @@ -37,5 +37,5 @@ jobs: - name: Commit changes uses: EndBug/add-and-commit@v9 with: - default_author: github_actions + default_author: user_info message: "${{ github.event.pull_request.title }} for all modules" diff --git a/.github/workflows/pr-reminder.yml b/.github/workflows/pr-reminder.yml new file mode 100644 index 000000000000..ade3fbdcde7e --- /dev/null +++ b/.github/workflows/pr-reminder.yml @@ -0,0 +1,52 @@ +name: PR Review Reminder + +on: + schedule: + - cron: '0 9 * * 1-5' # Every weekday at 9:00 AM UTC + +permissions: + pull-requests: read + +jobs: + pr-review: + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: List open pull requests using GitHub Script + uses: actions/github-script@v7 + id: pr-list + with: + script: | + const { data: pullRequests } = await github.rest.pulls.list({ + owner: context.repo.owner, + repo: context.repo.repo, + state: 'open', + }); + + let table = ''; + pullRequests.forEach(pr => { + const assignees = pr.assignees.length > 0 ? `Assignees: ${pr.assignees.map(assignee => assignee.login).join(', ')}` : 'No assignees'; + table += pr.draft ? '' : ` + Title: ${pr.title} + Link: <${pr.html_url}> + Assigness: ${assignees} + `; + }); + return table; + + - name: Send Slack Reminder + if: steps.pr-list.outputs.result != '' + uses: rtCamp/action-slack-notify@v2.3.0 + env: + SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }} + SLACK_CHANNEL: pr-github + SLACK_USERNAME: PR-Reminder + MSG_MINIMAL: true + SLACK_ICON_EMOJI: ":think:" + SLACK_COLOR: good + SLACKIFY_MARKDOWN: true + SLACK_TITLE: Daily Pull Request Review Reminder + SLACK_MESSAGE: | + ${{ steps.pr-list.outputs.result }} diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 8c77ba9700e7..48c7e82a9677 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -144,8 +144,7 @@ jobs: name: "${{ github.sha }}-e2e-coverage" path: ./tests/e2e-profile.out - test-system: - needs: [tests, test-integration, test-e2e] + test-system: # v2 system tests are in v2-test.yml runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 @@ -175,16 +174,6 @@ jobs: run: | sudo apt-get install -y musl - name: system tests v1 - if: env.GIT_DIFF - run: | - COSMOS_BUILD_OPTIONS=legacy make test-system - - uses: actions/upload-artifact@v3 - if: failure() - with: - name: "testnet-setup" - path: ./systemtests/testnet/ - retention-days: 3 - - name: system tests v2 if: env.GIT_DIFF run: | make test-system @@ -937,6 +926,29 @@ jobs: with: projectBaseDir: x/accounts/ + test-x-accounts-base: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-go@v5 + with: + go-version: "1.23" + check-latest: true + cache: true + cache-dependency-path: x/accounts/defaults/base/go.sum + - uses: technote-space/get-diff-action@v6.1.2 + id: git_diff + with: + PATTERNS: | + x/accounts/defaults/base/**/*.go + x/accounts/defaults/base/go.mod + x/accounts/defaults/base/go.sum + - name: tests + if: env.GIT_DIFF + run: | + cd x/accounts/defaults/base + go test -mod=readonly -timeout 30m -coverprofile=coverage.out -covermode=atomic -tags='norace ledger test_ledger_mock' ./... + test-x-accounts-lockup: runs-on: ubuntu-latest steps: diff --git a/.github/workflows/v2-test.yml b/.github/workflows/v2-test.yml index 6896f803a2c1..e26e12c0f402 100644 --- a/.github/workflows/v2-test.yml +++ b/.github/workflows/v2-test.yml @@ -109,3 +109,43 @@ jobs: if: env.GIT_DIFF run: | cd server/v2/cometbft && go test -mod=readonly -race -timeout 30m -tags='ledger test_ledger_mock' + + test-system-v2: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-tags: true + - uses: actions/setup-go@v5 + with: + go-version: "1.23" + check-latest: true + cache: true + cache-dependency-path: | + simapp/v2/go.sum + systemtest/go.sum + - uses: technote-space/get-diff-action@v6.1.2 + id: git_diff + with: + PATTERNS: | + **/*.go + go.mod + go.sum + **/go.mod + **/go.sum + **/Makefile + Makefile + - name: Install musl lib for simd (docker) binary + if: env.GIT_DIFF + run: | + sudo apt-get install -y musl + - name: system tests v2 + if: env.GIT_DIFF + run: | + COSMOS_BUILD_OPTIONS=v2 make test-system + - uses: actions/upload-artifact@v3 + if: failure() + with: + name: "testnet-setup" + path: ./systemtests/testnet/ + retention-days: 3 diff --git a/.golangci.yml b/.golangci.yml index a976100278e9..9fa8a3398ac3 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -13,7 +13,7 @@ linters: - dogsled - errcheck - errorlint - - exportloopref + - copyloopvar - gci - goconst - gocritic @@ -45,15 +45,15 @@ issues: - crypto/keys/secp256k1/internal/* - types/coin_regex.go exclude-rules: - - text: "ST1003:" + - text: "ST1003:" # We are fine with our current naming linters: - stylecheck # FIXME: Disabled until golangci-lint updates stylecheck with this fix: # https://github.com/dominikh/go-tools/issues/389 - - text: "ST1016:" + - text: "ST1016:" # Ok with inconsistent receiver names linters: - stylecheck - - path: "migrations" + - path: "migrations" # migraitions always use deprecated code text: "SA1019:" linters: - staticcheck @@ -72,9 +72,9 @@ issues: - text: "SA1019: params.SendEnabled is deprecated" # TODO remove once ready to remove from the sdk linters: - staticcheck - - text: "SA1029: Inappropriate key in context.WithValue" # TODO remove this when dependency is updated + - text: "G115: integer overflow conversion" # We are doing this everywhere. linters: - - staticcheck + - gosec - text: "leading space" linters: - nolintlint diff --git a/CHANGELOG.md b/CHANGELOG.md index 021b7800dbd2..f86a2748fdce 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -43,20 +43,31 @@ Every module contains its own CHANGELOG.md. Please refer to the module you are i ### Features * (baseapp) [#20291](https://github.com/cosmos/cosmos-sdk/pull/20291) Simulate nested messages. -* (cli) [#21372](https://github.com/cosmos/cosmos-sdk/pull/21372) Add a `bulk-add-genesis-account` genesis command to add many genesis accounts at once. * (crypto/keyring) [#21653](https://github.com/cosmos/cosmos-sdk/pull/21653) New Linux-only backend that adds Linux kernel's `keyctl` support. * (runtime) [#21704](https://github.com/cosmos/cosmos-sdk/pull/21704) Add StoreLoader in simappv2. +* (client/keys) [#21829](https://github.com/cosmos/cosmos-sdk/pull/21829) Add support for importing hex key using standard input. +* (x/validate) [#21822](https://github.com/cosmos/cosmos-sdk/pull/21822) New module solely responsible for providing ante/post handlers and tx validators for v2. It can be extended by the app developer to provide extra tx validators. + * In comparison to x/auth/tx/config, there is no app config to skip ante/post handlers, as overwriting them in baseapp or not injecting the x/validate module has the same effect. +* (baeapp) [#21979](https://github.com/cosmos/cosmos-sdk/pull/21979) Create CheckTxHandler to allow extending the logic of CheckTx. ### Improvements -* (genutil) [#21701](https://github.com/cosmos/cosmos-sdk/pull/21701) Improved error messages for genesis validation. +* (crypto/ledger) [#22116](https://github.com/cosmos/cosmos-sdk/pull/22116) Improve error message when deriving paths using index >100 +* (sims) [#21613](https://github.com/cosmos/cosmos-sdk/pull/21613) Add sims2 framework and factory methods for simpler message factories in modules +* (modules) [#21963](https://github.com/cosmos/cosmos-sdk/pull/21963) Duplicatable metrics are no more collected in modules. They were unecessary overhead. ### Bug Fixes -* (baseapp) [#21256](https://github.com/cosmos/cosmos-sdk/pull/21256) Halt height will not commit the block indicated, meaning that if halt-height is set to 10, only blocks until 9 (included) will be committed. This is to go back to the original behavior before a change was introduced in v0.50.0. +* (sims) [#21952](https://github.com/cosmos/cosmos-sdk/pull/21952) Use liveness matrix for validator sign status in sims +* (sims) [#21906](https://github.com/cosmos/cosmos-sdk/pull/21906) Skip sims test when running dry on validators +* (cli) [#21919](https://github.com/cosmos/cosmos-sdk/pull/21919) Query address-by-acc-num by account_id instead of id. ### API Breaking Changes +* (types/mempool) [#21744](https://github.com/cosmos/cosmos-sdk/pull/21744) Update types/mempool.Mempool interface to take decoded transactions. This avoid to decode the transaction twice. +* (x/auth/tx/config) [#21822](https://github.com/cosmos/cosmos-sdk/pull/21822) Sign mode textual is no more automatically added to tx config when using runtime. Should be added manually on the server side. +* (x/auth/tx/config) [#21822](https://github.com/cosmos/cosmos-sdk/pull/21822) This depinject module now only provide txconfig and tx config options. `x/validate` now handles the providing of ante/post handlers, alongside tx validators for v2. The corresponding app config options have been removed from the depinject module config. + ### Deprecated ## [v0.52.0](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.52.0) - 2024-XX-XX @@ -132,6 +143,7 @@ Every module contains its own CHANGELOG.md. Please refer to the module you are i * (internal) [#21412](https://github.com/cosmos/cosmos-sdk/pull/21412) Using unsafe.String and unsafe.SliceData. * (client) [#21436](https://github.com/cosmos/cosmos-sdk/pull/21436) Use `address.Codec` from client.Context in `tx.Sign`. * (x/genutil) [#21249](https://github.com/cosmos/cosmos-sdk/pull/21249) Incremental JSON parsing for AppGenesis where possible. +* (testnet) [#21941](https://github.com/cosmos/cosmos-sdk/pull/21941) Regenerate addrbook.json for in place testnet. ### Bug Fixes @@ -234,6 +246,28 @@ Every module contains its own CHANGELOG.md. Please refer to the module you are i * (module) [#19370](https://github.com/cosmos/cosmos-sdk/pull/19370) Deprecate `module.Configurator`, use `appmodule.HasMigrations` and `appmodule.HasServices` instead from Core API. * (types) [#21435](https://github.com/cosmos/cosmos-sdk/pull/21435) The `String()` method on `AccAddress`, `ValAddress` and `ConsAddress` have been deprecated. This is done because those are still using the deprecated global `sdk.Config`. Use an `address.Codec` instead. +## [v0.50.10](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.50.10) - 2024-09-20 + +## Features + +* (cli) [#20779](https://github.com/cosmos/cosmos-sdk/pull/20779) Added `module-hash-by-height` command to query and retrieve module hashes at a specified blockchain height, enhancing debugging capabilities. +* (cli) [#21372](https://github.com/cosmos/cosmos-sdk/pull/21372) Added a `bulk-add-genesis-account` genesis command to add many genesis accounts at once. +* (types/collections) [#21724](https://github.com/cosmos/cosmos-sdk/pull/21724) Added `LegacyDec` collection value. + +### Improvements + +* (x/bank) [#21460](https://github.com/cosmos/cosmos-sdk/pull/21460) Added `Sender` attribute in `MsgMultiSend` event. +* (genutil) [#21701](https://github.com/cosmos/cosmos-sdk/pull/21701) Improved error messages for genesis validation. +* (testutil/integration) [#21816](https://github.com/cosmos/cosmos-sdk/pull/21816) Allow to pass baseapp options in `NewIntegrationApp`. + +### Bug Fixes + +* (runtime) [#21769](https://github.com/cosmos/cosmos-sdk/pull/21769) Fix baseapp options ordering to avoid overwriting options set by modules. +* (x/consensus) [#21493](https://github.com/cosmos/cosmos-sdk/pull/21493) Fix regression that prevented to upgrade to > v0.50.7 without consensus version params. +* (baseapp) [#21256](https://github.com/cosmos/cosmos-sdk/pull/21256) Halt height will not commit the block indicated, meaning that if halt-height is set to 10, only blocks until 9 (included) will be committed. This is to go back to the original behavior before a change was introduced in v0.50.0. +* (baseapp) [#21444](https://github.com/cosmos/cosmos-sdk/pull/21444) Follow-up, Return PreBlocker events in FinalizeBlockResponse. +* (baseapp) [#21413](https://github.com/cosmos/cosmos-sdk/pull/21413) Fix data race in sdk mempool. + ## [v0.50.9](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.50.9) - 2024-08-07 ## Bug Fixes @@ -742,6 +776,13 @@ Every module contains its own CHANGELOG.md. Please refer to the module you are i * (x/staking) [#14567](https://github.com/cosmos/cosmos-sdk/pull/14567) The `delegator_address` field of `MsgCreateValidator` has been deprecated. The validator address bytes and delegator address bytes refer to the same account while creating validator (defer only in bech32 notation). +## [v0.47.14](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.47.14) - 2024-09-20 + +### Improvements + +* [#21295](https://github.com/cosmos/cosmos-sdk/pull/21295) Bump to gogoproto v1.7.0. +* [#21295](https://github.com/cosmos/cosmos-sdk/pull/21295) Remove usage of `slices.SortFunc` due to API break in used versions. + ## [v0.47.13](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.47.13) - 2024-07-15 ### Bug Fixes diff --git a/CODING_GUIDELINES.md b/CODING_GUIDELINES.md index 60aeb1192746..59cd1e25e9b6 100644 --- a/CODING_GUIDELINES.md +++ b/CODING_GUIDELINES.md @@ -104,7 +104,7 @@ Make sure your code is well tested: We expect tests to use `require` or `assert` rather than `t.Skip` or `t.Fail`, unless there is a reason to do otherwise. When testing a function under a variety of different inputs, we prefer to use -[table driven tests](https://github.com/golang/go/wiki/TableDrivenTests). +[table driven tests](https://go.dev/wiki/TableDrivenTests). Table driven test error messages should follow the following format `, tc #, i #`. `` is an optional short description of what's failing, `tc` is the diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e5e5a88b1cfc..10b2e3396fac 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -48,7 +48,7 @@ contributors, the general procedure for contributing has been established: to begin work. 5. To submit your work as a contribution to the repository follow standard GitHub best practices. See [pull request guideline](#pull-requests) below. -**Note:** For very small or blatantly obvious problems, you are +**Note 1:** For very small or blatantly obvious problems, you are not required to an open issue to submit a PR, but be aware that for more complex problems/features, if a PR is opened before an adequate design discussion has taken place in a GitHub issue, that PR runs a high likelihood of being rejected. @@ -128,9 +128,7 @@ NOTE: when merging, GitHub will squash commits and rebase on top of the main. ### Pull Request Templates -There are three PR templates. The [default template](./.github/PULL_REQUEST_TEMPLATE.md) is for types `fix`, `feat`, and `refactor`. We also have a [docs template](./.github/PULL_REQUEST_TEMPLATE/docs.md) for documentation changes. When previewing a PR before it has been opened, you can change the template by adding one of the following parameters to the url: - -* `template=docs.md` +There are three PR templates. The [default template](./.github/PULL_REQUEST_TEMPLATE.md) is used for PR types such as `fix`, `feat`,`docs`, and `refactor`, among others. These are just a few examples. For more details, please refer to the default template. ### Pull Request Accountability @@ -202,7 +200,7 @@ that you would like early feedback and tagging whoever you would like to receive Codeowners are marked automatically as the reviewers. All PRs require at least two review approvals before they can be merged (one review might be acceptable in -the case of minor changes to [docs](./.github/PULL_REQUEST_TEMPLATE/docs.md) changes that do not affect production code). Each PR template has a reviewers checklist that must be completed before the PR can be merged. Each reviewer is responsible +the case of minor changes to docs changes that do not affect production code). Each PR template has a reviewers checklist that must be completed before the PR can be merged. Each reviewer is responsible for all checked items unless they have indicated otherwise by leaving their handle next to specific items. In addition, use the following review explanations: @@ -238,7 +236,7 @@ Within the Cosmos SDK we have two forms of documenting decisions, Request For Co ## Dependencies -We use [Go Modules](https://github.com/golang/go/wiki/Modules) to manage +We use [Go Modules](https://go.dev/wiki/Modules) to manage dependency versions. The main branch of every Cosmos repository should just build with `go get`, @@ -272,9 +270,9 @@ When extracting a package to its own go modules, some extra steps are required, ## Protobuf -We use [Protocol Buffers](https://developers.google.com/protocol-buffers) along with [gogoproto](https://github.com/cosmos/gogoproto) to generate code for use in Cosmos SDK. +We use [Protocol Buffers](https://protobuf.dev) along with [gogoproto](https://github.com/cosmos/gogoproto) to generate code for use in Cosmos SDK. -For deterministic behavior around Protobuf tooling, everything is containerized using Docker. Make sure to have Docker installed on your machine, or head to [Docker's website](https://docs.docker.com/get-docker/) to install it. +For deterministic behavior around Protobuf tooling, everything is containerized using Docker. Make sure to have Docker installed on your machine, or head to [Docker's website](https://docs.docker.com/get-started/get-docker/) to install it. For formatting code in `.proto` files, you can run `make proto-format` command. @@ -302,7 +300,7 @@ For example, in vscode your `.vscode/settings.json` should look like: User-facing repos should adhere to the trunk based development branching model: https://trunkbaseddevelopment.com. User branches should start with a user name, example: `{moniker}/{issue#}-branch-name`. -The Cosmos SDK repository is a [multi Go module](https://github.com/golang/go/wiki/Modules#is-it-possible-to-add-a-module-to-a-multi-module-repository) repository. It means that we have more than one Go module in a single repository. +The Cosmos SDK repository is a [multi Go module](https://go.dev/wiki/Modules#is-it-possible-to-add-a-module-to-a-multi-module-repository) repository. It means that we have more than one Go module in a single repository. The Cosmos SDK utilizes [semantic versioning](https://semver.org/). diff --git a/Makefile b/Makefile index 067b5d4f6103..775dc0cd3d7c 100644 --- a/Makefile +++ b/Makefile @@ -10,7 +10,7 @@ include scripts/build/build.mk .DEFAULT_GOAL := help -#? go.sum: Run go mod tidy and ensure dependencies have not been modified +#? go.sum: Run go mod tidy and ensure dependencies have not been modified. go.sum: go.mod echo "Ensure dependencies have not been modified ..." >&2 go mod verify diff --git a/RELEASE_PROCESS.md b/RELEASE_PROCESS.md index 9bbb8817f862..e676be0d4ab1 100644 --- a/RELEASE_PROCESS.md +++ b/RELEASE_PROCESS.md @@ -212,9 +212,9 @@ Their responsibilities include: Currently residing Stable Release Managers: -* @tac0turtle - Marko Baricevic -* @julienrbrt - Julien Robert - +* [@tac0turtle - Marko Baricevic](https://github.com/tac0turtle) +* [@julienrbrt - Julien Robert](https://github.com/julienrbrt) + ## Cosmos SDK Modules Tagging Strategy The Cosmos SDK repository is a mono-repo where its Go modules have a different release process and cadence than the Cosmos SDK itself. diff --git a/SECURITY.md b/SECURITY.md index 94da755d8f47..30ae0fe0eb74 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -57,13 +57,8 @@ If you follow these guidelines when reporting an issue to us, we commit to: ### More information -* See [TIMELINE.md] for an example timeline of a disclosure. -* See [DISCLOSURE.md] to see more into the inner workings of the disclosure - process. * See [EXAMPLES.md] for some of the examples that we are interested in for the bug bounty program. [h1]: https://hackerone.com/cosmos -[TIMELINE.md]: https://github.com/cosmos/security/blob/main/TIMELINE.md -[DISCLOSURE.md]: https://github.com/cosmos/security/blob/main/DISCLOSURE.md -[EXAMPLES.md]: https://github.com/cosmos/security/blob/main/EXAMPLES.md +[EXAMPLES.md]: https://github.com/interchainio/security/blob/main/resources/CLASSIFICATION_MATRIX.md#real-world-examples diff --git a/UPGRADING.md b/UPGRADING.md index d7c8752ae476..812cab038576 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -44,7 +44,7 @@ To be able to simulate nested messages within a transaction, message types conta the nested messages. By implementing this interface, the BaseApp can simulate these nested messages during transaction simulation. -## [v0.52.x](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.52.0-alpha.0) +## [v0.52.x](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.52.0-beta.1) Documentation to migrate an application from v0.50.x to server/v2 is available elsewhere. It is additional to the changes described here. @@ -53,7 +53,7 @@ It is additional to the changes described here. In this section we describe the changes made in Cosmos SDK' SimApp. **These changes are directly applicable to your application wiring.** -Please read this section first, but for an exhaustive list of changes, refer to the [CHANGELOG](./simapp/CHANGELOG.md). +Please read this section first, but for an exhaustive list of changes, refer to the [CHANGELOG](https://github.com/cosmos/cosmos-sdk/blob/main/simapp/CHANGELOG.md). #### Client (`root.go`) @@ -106,7 +106,7 @@ For non depinject users, simply call `RegisterLegacyAminoCodec` and `RegisterInt Additionally, thanks to the genesis simplification, as explained in [the genesis interface update](#genesis-interface), the module manager `InitGenesis` and `ExportGenesis` methods do not require the codec anymore. -##### GRPC WEB +##### gRPC Web Grpc-web embedded client has been removed from the server. If you would like to use grpc-web, you can use the [envoy proxy](https://www.envoyproxy.io/docs/envoy/latest/start/start). Here's how to set it up: @@ -195,7 +195,9 @@ Grpc-web embedded client has been removed from the server. If you would like to This indicates that Envoy has started and is ready to proxy requests. + 6. Update your client applications to connect to Envoy (http://localhost:8080 by default). + @@ -317,6 +319,11 @@ used as a TTL for the transaction and is used to provide replay protection. See [ADR-070](https://github.com/cosmos/cosmos-sdk/blob/main/docs/architecture/adr-070-unordered-transactions.md) for more details. +#### Sign Mode Textual + +With the split of `x/auth/tx/config` in two (x/auth/tx/config as depinject module for txconfig and tx options) and `x/validate`, sign mode textual is no more automatically configured when using runtime (it was previously the case). +For the same instructions than for legacy app wiring to enable sign mode textual (see in v0.50 UPGRADING documentation). + ### Depinject `app_config.go` / `app.yml` With the introduction of [environment in modules](#core-api), depinject automatically creates the environment for all modules. @@ -457,7 +464,7 @@ if err != nil { } ``` -### `x/crisis` +#### `x/crisis` The `x/crisis` module was removed due to it not being supported or functional any longer. @@ -501,6 +508,11 @@ storetypes.StoreUpgrades{ } ``` +#### `x/validate` + +Introducing `x/validate` a module that is solely used for registering default ante/post handlers and global tx validators when using runtime and runtime/v2. If you wish to set your custom ante/post handlers, no need to use this module. +You can however always extend them by adding extra tx validators (see `x/validate` documentation). + ## [v0.50.x](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.50.0-alpha.0) ### Migration to CometBFT (Part 2) @@ -626,7 +638,7 @@ simd config migrate v0.50 If you were using ` config [key]` or ` config [key] [value]` to set and get values from the `client.toml`, replace it with ` config get client [key]` and ` config set client [key] [value]`. The extra verbosity is due to the extra functionalities added in config. -More information about [confix](https://docs.cosmos.network/main/tooling/confix) and how to add it in your application binary in the [documentation](https://docs.cosmos.network/main/tooling/confix). +More information about [confix](https://docs.cosmos.network/main/build/tooling/confix) and how to add it in your application binary in the [documentation](https://docs.cosmos.network/main/build/tooling/confix). #### gRPC-Web @@ -934,6 +946,55 @@ To find out more please read the [signer field](https://github.com/cosmos/cosmos For ante handler construction via `ante.NewAnteHandler`, the field `ante.HandlerOptions.SignModeHandler` has been updated to `x/tx/signing/HandlerMap` from `x/auth/signing/SignModeHandler`. Callers typically fetch this value from `client.TxConfig.SignModeHandler()` (which is also changed) so this change should be transparent to most users. +##### Account Migration Guide: x/auth to x/accounts + +Users can now migrate accounts from `x/auth` to `x/accounts` using the `auth.MsgMigrateAccount` message. Currently, this migration is only supported for `BaseAccount` due to security considerations. + +###### Migration Process + +The migration process allows an auth BaseAccount to migrate to any kind of x/accounts supported account type, here we will show how to migrate from a legacy x/auth `BaseAccount` to a `x/accounts` `BaseAccount` + +####### Migrating to x/accounts/defaults/base + +To migrate to the `BaseAccount` in `x/accounts`, follow these steps: + +1. Send a `basev1.MsgInit` message. +2. This process allows you to: + - Switch to a new public key + - Reset your sequence number + +> **Important**: If you intend to keep the same public key, ensure you use your current sequence number. + +###### Example: x/auth.MsgMigrateAccount + +Here's an example of the `x/auth.MsgMigrateAccount` message structure: + +```json +{ + "signer": "cosmos1w43tr39v3lzvxz969e4ty9a74rq9nw7563tqvy", + "account_type": "base", + "account_init_msg": { + "@type": "/cosmos.accounts.defaults.base.v1.MsgInit", + "pub_key": { + "@type": "/cosmos.crypto.secp256k1.PubKey", + "key": "AkeoE1z32tlQyE7xpx3v+JE9XJL0trVQBFoDCn0pGl3w" + }, + "init_sequence": "100" + } +} +``` + +**Field Descriptions** + +- `signer`: The address of the account you want to migrate from. +- `account_type`: The new account type you want to migrate to (depends on what's installed on the chain). +- `account_init_msg`: The custom initialization message for the new account. + - `@type`: Specifies the type of account (in this case, x/accounts base account). + - `pub_key`: The public key for the account. You can migrate to a different public key if desired. + - `init_sequence`: The new sequence number for the account. + +> **Warning**: If you're keeping the same public key, make sure to use your current sequence number to prevent potential replay attacks. + #### `x/capability` Capability has been moved to [IBC Go](https://github.com/cosmos/ibc-go). IBC v8 will contain the necessary changes to incorporate the new module location. diff --git a/api/cosmos/accounts/defaults/base/v1/base.pulsar.go b/api/cosmos/accounts/defaults/base/v1/base.pulsar.go index f1136248cde1..bd568f086f2f 100644 --- a/api/cosmos/accounts/defaults/base/v1/base.pulsar.go +++ b/api/cosmos/accounts/defaults/base/v1/base.pulsar.go @@ -14,14 +14,16 @@ import ( ) var ( - md_MsgInit protoreflect.MessageDescriptor - fd_MsgInit_pub_key protoreflect.FieldDescriptor + md_MsgInit protoreflect.MessageDescriptor + fd_MsgInit_pub_key protoreflect.FieldDescriptor + fd_MsgInit_init_sequence protoreflect.FieldDescriptor ) func init() { file_cosmos_accounts_defaults_base_v1_base_proto_init() md_MsgInit = File_cosmos_accounts_defaults_base_v1_base_proto.Messages().ByName("MsgInit") fd_MsgInit_pub_key = md_MsgInit.Fields().ByName("pub_key") + fd_MsgInit_init_sequence = md_MsgInit.Fields().ByName("init_sequence") } var _ protoreflect.Message = (*fastReflection_MsgInit)(nil) @@ -95,6 +97,12 @@ func (x *fastReflection_MsgInit) Range(f func(protoreflect.FieldDescriptor, prot return } } + if x.InitSequence != uint64(0) { + value := protoreflect.ValueOfUint64(x.InitSequence) + if !f(fd_MsgInit_init_sequence, value) { + return + } + } } // Has reports whether a field is populated. @@ -112,6 +120,8 @@ func (x *fastReflection_MsgInit) Has(fd protoreflect.FieldDescriptor) bool { switch fd.FullName() { case "cosmos.accounts.defaults.base.v1.MsgInit.pub_key": return x.PubKey != nil + case "cosmos.accounts.defaults.base.v1.MsgInit.init_sequence": + return x.InitSequence != uint64(0) default: if fd.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.accounts.defaults.base.v1.MsgInit")) @@ -130,6 +140,8 @@ func (x *fastReflection_MsgInit) Clear(fd protoreflect.FieldDescriptor) { switch fd.FullName() { case "cosmos.accounts.defaults.base.v1.MsgInit.pub_key": x.PubKey = nil + case "cosmos.accounts.defaults.base.v1.MsgInit.init_sequence": + x.InitSequence = uint64(0) default: if fd.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.accounts.defaults.base.v1.MsgInit")) @@ -149,6 +161,9 @@ func (x *fastReflection_MsgInit) Get(descriptor protoreflect.FieldDescriptor) pr case "cosmos.accounts.defaults.base.v1.MsgInit.pub_key": value := x.PubKey return protoreflect.ValueOfMessage(value.ProtoReflect()) + case "cosmos.accounts.defaults.base.v1.MsgInit.init_sequence": + value := x.InitSequence + return protoreflect.ValueOfUint64(value) default: if descriptor.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.accounts.defaults.base.v1.MsgInit")) @@ -171,6 +186,8 @@ func (x *fastReflection_MsgInit) Set(fd protoreflect.FieldDescriptor, value prot switch fd.FullName() { case "cosmos.accounts.defaults.base.v1.MsgInit.pub_key": x.PubKey = value.Message().Interface().(*anypb.Any) + case "cosmos.accounts.defaults.base.v1.MsgInit.init_sequence": + x.InitSequence = value.Uint() default: if fd.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.accounts.defaults.base.v1.MsgInit")) @@ -196,6 +213,8 @@ func (x *fastReflection_MsgInit) Mutable(fd protoreflect.FieldDescriptor) protor x.PubKey = new(anypb.Any) } return protoreflect.ValueOfMessage(x.PubKey.ProtoReflect()) + case "cosmos.accounts.defaults.base.v1.MsgInit.init_sequence": + panic(fmt.Errorf("field init_sequence of message cosmos.accounts.defaults.base.v1.MsgInit is not mutable")) default: if fd.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.accounts.defaults.base.v1.MsgInit")) @@ -212,6 +231,8 @@ func (x *fastReflection_MsgInit) NewField(fd protoreflect.FieldDescriptor) proto case "cosmos.accounts.defaults.base.v1.MsgInit.pub_key": m := new(anypb.Any) return protoreflect.ValueOfMessage(m.ProtoReflect()) + case "cosmos.accounts.defaults.base.v1.MsgInit.init_sequence": + return protoreflect.ValueOfUint64(uint64(0)) default: if fd.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.accounts.defaults.base.v1.MsgInit")) @@ -285,6 +306,9 @@ func (x *fastReflection_MsgInit) ProtoMethods() *protoiface.Methods { l = options.Size(x.PubKey) n += 1 + l + runtime.Sov(uint64(l)) } + if x.InitSequence != 0 { + n += 1 + runtime.Sov(uint64(x.InitSequence)) + } if x.unknownFields != nil { n += len(x.unknownFields) } @@ -314,6 +338,11 @@ func (x *fastReflection_MsgInit) ProtoMethods() *protoiface.Methods { i -= len(x.unknownFields) copy(dAtA[i:], x.unknownFields) } + if x.InitSequence != 0 { + i = runtime.EncodeVarint(dAtA, i, uint64(x.InitSequence)) + i-- + dAtA[i] = 0x10 + } if x.PubKey != nil { encoded, err := options.Marshal(x.PubKey) if err != nil { @@ -413,6 +442,25 @@ func (x *fastReflection_MsgInit) ProtoMethods() *protoiface.Methods { return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, err } iNdEx = postIndex + case 2: + if wireType != 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field InitSequence", wireType) + } + x.InitSequence = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow + } + if iNdEx >= l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + x.InitSequence |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } default: iNdEx = preIndex skippy, err := runtime.Skip(dAtA[iNdEx:]) @@ -3167,6 +3215,9 @@ type MsgInit struct { // pub_key defines a pubkey for the account arbitrary encapsulated. PubKey *anypb.Any `protobuf:"bytes,1,opt,name=pub_key,json=pubKey,proto3" json:"pub_key,omitempty"` + // init_sequence defines the initial sequence of the account. + // Defaults to zero if not set. + InitSequence uint64 `protobuf:"varint,2,opt,name=init_sequence,json=initSequence,proto3" json:"init_sequence,omitempty"` } func (x *MsgInit) Reset() { @@ -3196,6 +3247,13 @@ func (x *MsgInit) GetPubKey() *anypb.Any { return nil } +func (x *MsgInit) GetInitSequence() uint64 { + if x != nil { + return x.InitSequence + } + return 0 +} + // MsgInitResponse is the response returned after base account initialization. // This is empty. type MsgInitResponse struct { @@ -3425,45 +3483,48 @@ var file_cosmos_accounts_defaults_base_v1_base_proto_rawDesc = []byte{ 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x2e, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x1a, 0x19, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2f, 0x61, 0x6e, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x38, 0x0a, 0x07, 0x4d, 0x73, + 0x2f, 0x61, 0x6e, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x5d, 0x0a, 0x07, 0x4d, 0x73, 0x67, 0x49, 0x6e, 0x69, 0x74, 0x12, 0x2d, 0x0a, 0x07, 0x70, 0x75, 0x62, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x52, 0x06, 0x70, 0x75, - 0x62, 0x4b, 0x65, 0x79, 0x22, 0x11, 0x0a, 0x0f, 0x4d, 0x73, 0x67, 0x49, 0x6e, 0x69, 0x74, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x45, 0x0a, 0x0d, 0x4d, 0x73, 0x67, 0x53, 0x77, - 0x61, 0x70, 0x50, 0x75, 0x62, 0x4b, 0x65, 0x79, 0x12, 0x34, 0x0a, 0x0b, 0x6e, 0x65, 0x77, 0x5f, - 0x70, 0x75, 0x62, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x41, 0x6e, 0x79, 0x52, 0x09, 0x6e, 0x65, 0x77, 0x50, 0x75, 0x62, 0x4b, 0x65, 0x79, 0x22, 0x17, - 0x0a, 0x15, 0x4d, 0x73, 0x67, 0x53, 0x77, 0x61, 0x70, 0x50, 0x75, 0x62, 0x4b, 0x65, 0x79, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x0f, 0x0a, 0x0d, 0x51, 0x75, 0x65, 0x72, 0x79, - 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x22, 0x33, 0x0a, 0x15, 0x51, 0x75, 0x65, 0x72, - 0x79, 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x04, 0x52, 0x08, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x22, 0x0d, 0x0a, - 0x0b, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x75, 0x62, 0x4b, 0x65, 0x79, 0x22, 0x44, 0x0a, 0x13, - 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x75, 0x62, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x2d, 0x0a, 0x07, 0x70, 0x75, 0x62, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x52, 0x06, 0x70, 0x75, 0x62, 0x4b, - 0x65, 0x79, 0x42, 0x90, 0x02, 0x0a, 0x24, 0x63, 0x6f, 0x6d, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, - 0x73, 0x2e, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x2e, 0x64, 0x65, 0x66, 0x61, 0x75, - 0x6c, 0x74, 0x73, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x42, 0x09, 0x42, 0x61, 0x73, - 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x38, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, - 0x73, 0x64, 0x6b, 0x2e, 0x69, 0x6f, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, - 0x73, 0x2f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x2f, 0x64, 0x65, 0x66, 0x61, 0x75, - 0x6c, 0x74, 0x73, 0x2f, 0x62, 0x61, 0x73, 0x65, 0x2f, 0x76, 0x31, 0x3b, 0x62, 0x61, 0x73, 0x65, - 0x76, 0x31, 0xa2, 0x02, 0x04, 0x43, 0x41, 0x44, 0x42, 0xaa, 0x02, 0x20, 0x43, 0x6f, 0x73, 0x6d, - 0x6f, 0x73, 0x2e, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x2e, 0x44, 0x65, 0x66, 0x61, - 0x75, 0x6c, 0x74, 0x73, 0x2e, 0x42, 0x61, 0x73, 0x65, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x20, 0x43, - 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x5c, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x5c, 0x44, - 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x5c, 0x42, 0x61, 0x73, 0x65, 0x5c, 0x56, 0x31, 0xe2, - 0x02, 0x2c, 0x43, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x5c, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, - 0x73, 0x5c, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x5c, 0x42, 0x61, 0x73, 0x65, 0x5c, - 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, - 0x24, 0x43, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x3a, 0x3a, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, - 0x73, 0x3a, 0x3a, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x3a, 0x3a, 0x42, 0x61, 0x73, - 0x65, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x62, 0x4b, 0x65, 0x79, 0x12, 0x23, 0x0a, 0x0d, 0x69, 0x6e, 0x69, 0x74, 0x5f, 0x73, 0x65, 0x71, + 0x75, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0c, 0x69, 0x6e, 0x69, + 0x74, 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x22, 0x11, 0x0a, 0x0f, 0x4d, 0x73, 0x67, + 0x49, 0x6e, 0x69, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x45, 0x0a, 0x0d, + 0x4d, 0x73, 0x67, 0x53, 0x77, 0x61, 0x70, 0x50, 0x75, 0x62, 0x4b, 0x65, 0x79, 0x12, 0x34, 0x0a, + 0x0b, 0x6e, 0x65, 0x77, 0x5f, 0x70, 0x75, 0x62, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x52, 0x09, 0x6e, 0x65, 0x77, 0x50, 0x75, 0x62, + 0x4b, 0x65, 0x79, 0x22, 0x17, 0x0a, 0x15, 0x4d, 0x73, 0x67, 0x53, 0x77, 0x61, 0x70, 0x50, 0x75, + 0x62, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x0f, 0x0a, 0x0d, + 0x51, 0x75, 0x65, 0x72, 0x79, 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x22, 0x33, 0x0a, + 0x15, 0x51, 0x75, 0x65, 0x72, 0x79, 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, + 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, + 0x63, 0x65, 0x22, 0x0d, 0x0a, 0x0b, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x75, 0x62, 0x4b, 0x65, + 0x79, 0x22, 0x44, 0x0a, 0x13, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x75, 0x62, 0x4b, 0x65, 0x79, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2d, 0x0a, 0x07, 0x70, 0x75, 0x62, 0x5f, + 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x52, + 0x06, 0x70, 0x75, 0x62, 0x4b, 0x65, 0x79, 0x42, 0x90, 0x02, 0x0a, 0x24, 0x63, 0x6f, 0x6d, 0x2e, + 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x2e, + 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, + 0x42, 0x09, 0x42, 0x61, 0x73, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x38, 0x63, + 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x73, 0x64, 0x6b, 0x2e, 0x69, 0x6f, 0x2f, 0x61, 0x70, 0x69, 0x2f, + 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x2f, + 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x2f, 0x62, 0x61, 0x73, 0x65, 0x2f, 0x76, 0x31, + 0x3b, 0x62, 0x61, 0x73, 0x65, 0x76, 0x31, 0xa2, 0x02, 0x04, 0x43, 0x41, 0x44, 0x42, 0xaa, 0x02, + 0x20, 0x43, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, + 0x2e, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x2e, 0x42, 0x61, 0x73, 0x65, 0x2e, 0x56, + 0x31, 0xca, 0x02, 0x20, 0x43, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x5c, 0x41, 0x63, 0x63, 0x6f, 0x75, + 0x6e, 0x74, 0x73, 0x5c, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x5c, 0x42, 0x61, 0x73, + 0x65, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x2c, 0x43, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x5c, 0x41, 0x63, + 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x5c, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x5c, + 0x42, 0x61, 0x73, 0x65, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, + 0x61, 0x74, 0x61, 0xea, 0x02, 0x24, 0x43, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x3a, 0x3a, 0x41, 0x63, + 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x3a, 0x3a, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x73, + 0x3a, 0x3a, 0x42, 0x61, 0x73, 0x65, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x33, } var ( diff --git a/api/cosmos/auth/v1beta1/accounts.pulsar.go b/api/cosmos/auth/v1beta1/accounts.pulsar.go new file mode 100644 index 000000000000..fbf5ad3c01a4 --- /dev/null +++ b/api/cosmos/auth/v1beta1/accounts.pulsar.go @@ -0,0 +1,1095 @@ +// Code generated by protoc-gen-go-pulsar. DO NOT EDIT. +package authv1beta1 + +import ( + fmt "fmt" + runtime "github.com/cosmos/cosmos-proto/runtime" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoiface "google.golang.org/protobuf/runtime/protoiface" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + anypb "google.golang.org/protobuf/types/known/anypb" + io "io" + reflect "reflect" + sync "sync" +) + +var ( + md_QueryLegacyAccount protoreflect.MessageDescriptor +) + +func init() { + file_cosmos_auth_v1beta1_accounts_proto_init() + md_QueryLegacyAccount = File_cosmos_auth_v1beta1_accounts_proto.Messages().ByName("QueryLegacyAccount") +} + +var _ protoreflect.Message = (*fastReflection_QueryLegacyAccount)(nil) + +type fastReflection_QueryLegacyAccount QueryLegacyAccount + +func (x *QueryLegacyAccount) ProtoReflect() protoreflect.Message { + return (*fastReflection_QueryLegacyAccount)(x) +} + +func (x *QueryLegacyAccount) slowProtoReflect() protoreflect.Message { + mi := &file_cosmos_auth_v1beta1_accounts_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +var _fastReflection_QueryLegacyAccount_messageType fastReflection_QueryLegacyAccount_messageType +var _ protoreflect.MessageType = fastReflection_QueryLegacyAccount_messageType{} + +type fastReflection_QueryLegacyAccount_messageType struct{} + +func (x fastReflection_QueryLegacyAccount_messageType) Zero() protoreflect.Message { + return (*fastReflection_QueryLegacyAccount)(nil) +} +func (x fastReflection_QueryLegacyAccount_messageType) New() protoreflect.Message { + return new(fastReflection_QueryLegacyAccount) +} +func (x fastReflection_QueryLegacyAccount_messageType) Descriptor() protoreflect.MessageDescriptor { + return md_QueryLegacyAccount +} + +// Descriptor returns message descriptor, which contains only the protobuf +// type information for the message. +func (x *fastReflection_QueryLegacyAccount) Descriptor() protoreflect.MessageDescriptor { + return md_QueryLegacyAccount +} + +// Type returns the message type, which encapsulates both Go and protobuf +// type information. If the Go type information is not needed, +// it is recommended that the message descriptor be used instead. +func (x *fastReflection_QueryLegacyAccount) Type() protoreflect.MessageType { + return _fastReflection_QueryLegacyAccount_messageType +} + +// New returns a newly allocated and mutable empty message. +func (x *fastReflection_QueryLegacyAccount) New() protoreflect.Message { + return new(fastReflection_QueryLegacyAccount) +} + +// Interface unwraps the message reflection interface and +// returns the underlying ProtoMessage interface. +func (x *fastReflection_QueryLegacyAccount) Interface() protoreflect.ProtoMessage { + return (*QueryLegacyAccount)(x) +} + +// Range iterates over every populated field in an undefined order, +// calling f for each field descriptor and value encountered. +// Range returns immediately if f returns false. +// While iterating, mutating operations may only be performed +// on the current field descriptor. +func (x *fastReflection_QueryLegacyAccount) Range(f func(protoreflect.FieldDescriptor, protoreflect.Value) bool) { +} + +// Has reports whether a field is populated. +// +// Some fields have the property of nullability where it is possible to +// distinguish between the default value of a field and whether the field +// was explicitly populated with the default value. Singular message fields, +// member fields of a oneof, and proto2 scalar fields are nullable. Such +// fields are populated only if explicitly set. +// +// In other cases (aside from the nullable cases above), +// a proto3 scalar field is populated if it contains a non-zero value, and +// a repeated field is populated if it is non-empty. +func (x *fastReflection_QueryLegacyAccount) Has(fd protoreflect.FieldDescriptor) bool { + switch fd.FullName() { + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.auth.v1beta1.QueryLegacyAccount")) + } + panic(fmt.Errorf("message cosmos.auth.v1beta1.QueryLegacyAccount does not contain field %s", fd.FullName())) + } +} + +// Clear clears the field such that a subsequent Has call reports false. +// +// Clearing an extension field clears both the extension type and value +// associated with the given field number. +// +// Clear is a mutating operation and unsafe for concurrent use. +func (x *fastReflection_QueryLegacyAccount) Clear(fd protoreflect.FieldDescriptor) { + switch fd.FullName() { + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.auth.v1beta1.QueryLegacyAccount")) + } + panic(fmt.Errorf("message cosmos.auth.v1beta1.QueryLegacyAccount does not contain field %s", fd.FullName())) + } +} + +// Get retrieves the value for a field. +// +// For unpopulated scalars, it returns the default value, where +// the default value of a bytes scalar is guaranteed to be a copy. +// For unpopulated composite types, it returns an empty, read-only view +// of the value; to obtain a mutable reference, use Mutable. +func (x *fastReflection_QueryLegacyAccount) Get(descriptor protoreflect.FieldDescriptor) protoreflect.Value { + switch descriptor.FullName() { + default: + if descriptor.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.auth.v1beta1.QueryLegacyAccount")) + } + panic(fmt.Errorf("message cosmos.auth.v1beta1.QueryLegacyAccount does not contain field %s", descriptor.FullName())) + } +} + +// Set stores the value for a field. +// +// For a field belonging to a oneof, it implicitly clears any other field +// that may be currently set within the same oneof. +// For extension fields, it implicitly stores the provided ExtensionType. +// When setting a composite type, it is unspecified whether the stored value +// aliases the source's memory in any way. If the composite value is an +// empty, read-only value, then it panics. +// +// Set is a mutating operation and unsafe for concurrent use. +func (x *fastReflection_QueryLegacyAccount) Set(fd protoreflect.FieldDescriptor, value protoreflect.Value) { + switch fd.FullName() { + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.auth.v1beta1.QueryLegacyAccount")) + } + panic(fmt.Errorf("message cosmos.auth.v1beta1.QueryLegacyAccount does not contain field %s", fd.FullName())) + } +} + +// Mutable returns a mutable reference to a composite type. +// +// If the field is unpopulated, it may allocate a composite value. +// For a field belonging to a oneof, it implicitly clears any other field +// that may be currently set within the same oneof. +// For extension fields, it implicitly stores the provided ExtensionType +// if not already stored. +// It panics if the field does not contain a composite type. +// +// Mutable is a mutating operation and unsafe for concurrent use. +func (x *fastReflection_QueryLegacyAccount) Mutable(fd protoreflect.FieldDescriptor) protoreflect.Value { + switch fd.FullName() { + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.auth.v1beta1.QueryLegacyAccount")) + } + panic(fmt.Errorf("message cosmos.auth.v1beta1.QueryLegacyAccount does not contain field %s", fd.FullName())) + } +} + +// NewField returns a new value that is assignable to the field +// for the given descriptor. For scalars, this returns the default value. +// For lists, maps, and messages, this returns a new, empty, mutable value. +func (x *fastReflection_QueryLegacyAccount) NewField(fd protoreflect.FieldDescriptor) protoreflect.Value { + switch fd.FullName() { + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.auth.v1beta1.QueryLegacyAccount")) + } + panic(fmt.Errorf("message cosmos.auth.v1beta1.QueryLegacyAccount does not contain field %s", fd.FullName())) + } +} + +// WhichOneof reports which field within the oneof is populated, +// returning nil if none are populated. +// It panics if the oneof descriptor does not belong to this message. +func (x *fastReflection_QueryLegacyAccount) WhichOneof(d protoreflect.OneofDescriptor) protoreflect.FieldDescriptor { + switch d.FullName() { + default: + panic(fmt.Errorf("%s is not a oneof field in cosmos.auth.v1beta1.QueryLegacyAccount", d.FullName())) + } + panic("unreachable") +} + +// GetUnknown retrieves the entire list of unknown fields. +// The caller may only mutate the contents of the RawFields +// if the mutated bytes are stored back into the message with SetUnknown. +func (x *fastReflection_QueryLegacyAccount) GetUnknown() protoreflect.RawFields { + return x.unknownFields +} + +// SetUnknown stores an entire list of unknown fields. +// The raw fields must be syntactically valid according to the wire format. +// An implementation may panic if this is not the case. +// Once stored, the caller must not mutate the content of the RawFields. +// An empty RawFields may be passed to clear the fields. +// +// SetUnknown is a mutating operation and unsafe for concurrent use. +func (x *fastReflection_QueryLegacyAccount) SetUnknown(fields protoreflect.RawFields) { + x.unknownFields = fields +} + +// IsValid reports whether the message is valid. +// +// An invalid message is an empty, read-only value. +// +// An invalid message often corresponds to a nil pointer of the concrete +// message type, but the details are implementation dependent. +// Validity is not part of the protobuf data model, and may not +// be preserved in marshaling or other operations. +func (x *fastReflection_QueryLegacyAccount) IsValid() bool { + return x != nil +} + +// ProtoMethods returns optional fastReflectionFeature-path implementations of various operations. +// This method may return nil. +// +// The returned methods type is identical to +// "google.golang.org/protobuf/runtime/protoiface".Methods. +// Consult the protoiface package documentation for details. +func (x *fastReflection_QueryLegacyAccount) ProtoMethods() *protoiface.Methods { + size := func(input protoiface.SizeInput) protoiface.SizeOutput { + x := input.Message.Interface().(*QueryLegacyAccount) + if x == nil { + return protoiface.SizeOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Size: 0, + } + } + options := runtime.SizeInputToOptions(input) + _ = options + var n int + var l int + _ = l + if x.unknownFields != nil { + n += len(x.unknownFields) + } + return protoiface.SizeOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Size: n, + } + } + + marshal := func(input protoiface.MarshalInput) (protoiface.MarshalOutput, error) { + x := input.Message.Interface().(*QueryLegacyAccount) + if x == nil { + return protoiface.MarshalOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Buf: input.Buf, + }, nil + } + options := runtime.MarshalInputToOptions(input) + _ = options + size := options.Size(x) + dAtA := make([]byte, size) + i := len(dAtA) + _ = i + var l int + _ = l + if x.unknownFields != nil { + i -= len(x.unknownFields) + copy(dAtA[i:], x.unknownFields) + } + if input.Buf != nil { + input.Buf = append(input.Buf, dAtA...) + } else { + input.Buf = dAtA + } + return protoiface.MarshalOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Buf: input.Buf, + }, nil + } + unmarshal := func(input protoiface.UnmarshalInput) (protoiface.UnmarshalOutput, error) { + x := input.Message.Interface().(*QueryLegacyAccount) + if x == nil { + return protoiface.UnmarshalOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Flags: input.Flags, + }, nil + } + options := runtime.UnmarshalInputToOptions(input) + _ = options + dAtA := input.Buf + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow + } + if iNdEx >= l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, 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 protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: QueryLegacyAccount: wiretype end group for non-group") + } + if fieldNum <= 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: QueryLegacyAccount: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := runtime.Skip(dAtA[iNdEx:]) + if err != nil { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + if (iNdEx + skippy) > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + if !options.DiscardUnknown { + x.unknownFields = append(x.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + } + iNdEx += skippy + } + } + + if iNdEx > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, nil + } + return &protoiface.Methods{ + NoUnkeyedLiterals: struct{}{}, + Flags: protoiface.SupportMarshalDeterministic | protoiface.SupportUnmarshalDiscardUnknown, + Size: size, + Marshal: marshal, + Unmarshal: unmarshal, + Merge: nil, + CheckInitialized: nil, + } +} + +var ( + md_QueryLegacyAccountResponse protoreflect.MessageDescriptor + fd_QueryLegacyAccountResponse_account protoreflect.FieldDescriptor + fd_QueryLegacyAccountResponse_base protoreflect.FieldDescriptor +) + +func init() { + file_cosmos_auth_v1beta1_accounts_proto_init() + md_QueryLegacyAccountResponse = File_cosmos_auth_v1beta1_accounts_proto.Messages().ByName("QueryLegacyAccountResponse") + fd_QueryLegacyAccountResponse_account = md_QueryLegacyAccountResponse.Fields().ByName("account") + fd_QueryLegacyAccountResponse_base = md_QueryLegacyAccountResponse.Fields().ByName("base") +} + +var _ protoreflect.Message = (*fastReflection_QueryLegacyAccountResponse)(nil) + +type fastReflection_QueryLegacyAccountResponse QueryLegacyAccountResponse + +func (x *QueryLegacyAccountResponse) ProtoReflect() protoreflect.Message { + return (*fastReflection_QueryLegacyAccountResponse)(x) +} + +func (x *QueryLegacyAccountResponse) slowProtoReflect() protoreflect.Message { + mi := &file_cosmos_auth_v1beta1_accounts_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +var _fastReflection_QueryLegacyAccountResponse_messageType fastReflection_QueryLegacyAccountResponse_messageType +var _ protoreflect.MessageType = fastReflection_QueryLegacyAccountResponse_messageType{} + +type fastReflection_QueryLegacyAccountResponse_messageType struct{} + +func (x fastReflection_QueryLegacyAccountResponse_messageType) Zero() protoreflect.Message { + return (*fastReflection_QueryLegacyAccountResponse)(nil) +} +func (x fastReflection_QueryLegacyAccountResponse_messageType) New() protoreflect.Message { + return new(fastReflection_QueryLegacyAccountResponse) +} +func (x fastReflection_QueryLegacyAccountResponse_messageType) Descriptor() protoreflect.MessageDescriptor { + return md_QueryLegacyAccountResponse +} + +// Descriptor returns message descriptor, which contains only the protobuf +// type information for the message. +func (x *fastReflection_QueryLegacyAccountResponse) Descriptor() protoreflect.MessageDescriptor { + return md_QueryLegacyAccountResponse +} + +// Type returns the message type, which encapsulates both Go and protobuf +// type information. If the Go type information is not needed, +// it is recommended that the message descriptor be used instead. +func (x *fastReflection_QueryLegacyAccountResponse) Type() protoreflect.MessageType { + return _fastReflection_QueryLegacyAccountResponse_messageType +} + +// New returns a newly allocated and mutable empty message. +func (x *fastReflection_QueryLegacyAccountResponse) New() protoreflect.Message { + return new(fastReflection_QueryLegacyAccountResponse) +} + +// Interface unwraps the message reflection interface and +// returns the underlying ProtoMessage interface. +func (x *fastReflection_QueryLegacyAccountResponse) Interface() protoreflect.ProtoMessage { + return (*QueryLegacyAccountResponse)(x) +} + +// Range iterates over every populated field in an undefined order, +// calling f for each field descriptor and value encountered. +// Range returns immediately if f returns false. +// While iterating, mutating operations may only be performed +// on the current field descriptor. +func (x *fastReflection_QueryLegacyAccountResponse) Range(f func(protoreflect.FieldDescriptor, protoreflect.Value) bool) { + if x.Account != nil { + value := protoreflect.ValueOfMessage(x.Account.ProtoReflect()) + if !f(fd_QueryLegacyAccountResponse_account, value) { + return + } + } + if x.Base != nil { + value := protoreflect.ValueOfMessage(x.Base.ProtoReflect()) + if !f(fd_QueryLegacyAccountResponse_base, value) { + return + } + } +} + +// Has reports whether a field is populated. +// +// Some fields have the property of nullability where it is possible to +// distinguish between the default value of a field and whether the field +// was explicitly populated with the default value. Singular message fields, +// member fields of a oneof, and proto2 scalar fields are nullable. Such +// fields are populated only if explicitly set. +// +// In other cases (aside from the nullable cases above), +// a proto3 scalar field is populated if it contains a non-zero value, and +// a repeated field is populated if it is non-empty. +func (x *fastReflection_QueryLegacyAccountResponse) Has(fd protoreflect.FieldDescriptor) bool { + switch fd.FullName() { + case "cosmos.auth.v1beta1.QueryLegacyAccountResponse.account": + return x.Account != nil + case "cosmos.auth.v1beta1.QueryLegacyAccountResponse.base": + return x.Base != nil + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.auth.v1beta1.QueryLegacyAccountResponse")) + } + panic(fmt.Errorf("message cosmos.auth.v1beta1.QueryLegacyAccountResponse does not contain field %s", fd.FullName())) + } +} + +// Clear clears the field such that a subsequent Has call reports false. +// +// Clearing an extension field clears both the extension type and value +// associated with the given field number. +// +// Clear is a mutating operation and unsafe for concurrent use. +func (x *fastReflection_QueryLegacyAccountResponse) Clear(fd protoreflect.FieldDescriptor) { + switch fd.FullName() { + case "cosmos.auth.v1beta1.QueryLegacyAccountResponse.account": + x.Account = nil + case "cosmos.auth.v1beta1.QueryLegacyAccountResponse.base": + x.Base = nil + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.auth.v1beta1.QueryLegacyAccountResponse")) + } + panic(fmt.Errorf("message cosmos.auth.v1beta1.QueryLegacyAccountResponse does not contain field %s", fd.FullName())) + } +} + +// Get retrieves the value for a field. +// +// For unpopulated scalars, it returns the default value, where +// the default value of a bytes scalar is guaranteed to be a copy. +// For unpopulated composite types, it returns an empty, read-only view +// of the value; to obtain a mutable reference, use Mutable. +func (x *fastReflection_QueryLegacyAccountResponse) Get(descriptor protoreflect.FieldDescriptor) protoreflect.Value { + switch descriptor.FullName() { + case "cosmos.auth.v1beta1.QueryLegacyAccountResponse.account": + value := x.Account + return protoreflect.ValueOfMessage(value.ProtoReflect()) + case "cosmos.auth.v1beta1.QueryLegacyAccountResponse.base": + value := x.Base + return protoreflect.ValueOfMessage(value.ProtoReflect()) + default: + if descriptor.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.auth.v1beta1.QueryLegacyAccountResponse")) + } + panic(fmt.Errorf("message cosmos.auth.v1beta1.QueryLegacyAccountResponse does not contain field %s", descriptor.FullName())) + } +} + +// Set stores the value for a field. +// +// For a field belonging to a oneof, it implicitly clears any other field +// that may be currently set within the same oneof. +// For extension fields, it implicitly stores the provided ExtensionType. +// When setting a composite type, it is unspecified whether the stored value +// aliases the source's memory in any way. If the composite value is an +// empty, read-only value, then it panics. +// +// Set is a mutating operation and unsafe for concurrent use. +func (x *fastReflection_QueryLegacyAccountResponse) Set(fd protoreflect.FieldDescriptor, value protoreflect.Value) { + switch fd.FullName() { + case "cosmos.auth.v1beta1.QueryLegacyAccountResponse.account": + x.Account = value.Message().Interface().(*anypb.Any) + case "cosmos.auth.v1beta1.QueryLegacyAccountResponse.base": + x.Base = value.Message().Interface().(*BaseAccount) + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.auth.v1beta1.QueryLegacyAccountResponse")) + } + panic(fmt.Errorf("message cosmos.auth.v1beta1.QueryLegacyAccountResponse does not contain field %s", fd.FullName())) + } +} + +// Mutable returns a mutable reference to a composite type. +// +// If the field is unpopulated, it may allocate a composite value. +// For a field belonging to a oneof, it implicitly clears any other field +// that may be currently set within the same oneof. +// For extension fields, it implicitly stores the provided ExtensionType +// if not already stored. +// It panics if the field does not contain a composite type. +// +// Mutable is a mutating operation and unsafe for concurrent use. +func (x *fastReflection_QueryLegacyAccountResponse) Mutable(fd protoreflect.FieldDescriptor) protoreflect.Value { + switch fd.FullName() { + case "cosmos.auth.v1beta1.QueryLegacyAccountResponse.account": + if x.Account == nil { + x.Account = new(anypb.Any) + } + return protoreflect.ValueOfMessage(x.Account.ProtoReflect()) + case "cosmos.auth.v1beta1.QueryLegacyAccountResponse.base": + if x.Base == nil { + x.Base = new(BaseAccount) + } + return protoreflect.ValueOfMessage(x.Base.ProtoReflect()) + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.auth.v1beta1.QueryLegacyAccountResponse")) + } + panic(fmt.Errorf("message cosmos.auth.v1beta1.QueryLegacyAccountResponse does not contain field %s", fd.FullName())) + } +} + +// NewField returns a new value that is assignable to the field +// for the given descriptor. For scalars, this returns the default value. +// For lists, maps, and messages, this returns a new, empty, mutable value. +func (x *fastReflection_QueryLegacyAccountResponse) NewField(fd protoreflect.FieldDescriptor) protoreflect.Value { + switch fd.FullName() { + case "cosmos.auth.v1beta1.QueryLegacyAccountResponse.account": + m := new(anypb.Any) + return protoreflect.ValueOfMessage(m.ProtoReflect()) + case "cosmos.auth.v1beta1.QueryLegacyAccountResponse.base": + m := new(BaseAccount) + return protoreflect.ValueOfMessage(m.ProtoReflect()) + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.auth.v1beta1.QueryLegacyAccountResponse")) + } + panic(fmt.Errorf("message cosmos.auth.v1beta1.QueryLegacyAccountResponse does not contain field %s", fd.FullName())) + } +} + +// WhichOneof reports which field within the oneof is populated, +// returning nil if none are populated. +// It panics if the oneof descriptor does not belong to this message. +func (x *fastReflection_QueryLegacyAccountResponse) WhichOneof(d protoreflect.OneofDescriptor) protoreflect.FieldDescriptor { + switch d.FullName() { + default: + panic(fmt.Errorf("%s is not a oneof field in cosmos.auth.v1beta1.QueryLegacyAccountResponse", d.FullName())) + } + panic("unreachable") +} + +// GetUnknown retrieves the entire list of unknown fields. +// The caller may only mutate the contents of the RawFields +// if the mutated bytes are stored back into the message with SetUnknown. +func (x *fastReflection_QueryLegacyAccountResponse) GetUnknown() protoreflect.RawFields { + return x.unknownFields +} + +// SetUnknown stores an entire list of unknown fields. +// The raw fields must be syntactically valid according to the wire format. +// An implementation may panic if this is not the case. +// Once stored, the caller must not mutate the content of the RawFields. +// An empty RawFields may be passed to clear the fields. +// +// SetUnknown is a mutating operation and unsafe for concurrent use. +func (x *fastReflection_QueryLegacyAccountResponse) SetUnknown(fields protoreflect.RawFields) { + x.unknownFields = fields +} + +// IsValid reports whether the message is valid. +// +// An invalid message is an empty, read-only value. +// +// An invalid message often corresponds to a nil pointer of the concrete +// message type, but the details are implementation dependent. +// Validity is not part of the protobuf data model, and may not +// be preserved in marshaling or other operations. +func (x *fastReflection_QueryLegacyAccountResponse) IsValid() bool { + return x != nil +} + +// ProtoMethods returns optional fastReflectionFeature-path implementations of various operations. +// This method may return nil. +// +// The returned methods type is identical to +// "google.golang.org/protobuf/runtime/protoiface".Methods. +// Consult the protoiface package documentation for details. +func (x *fastReflection_QueryLegacyAccountResponse) ProtoMethods() *protoiface.Methods { + size := func(input protoiface.SizeInput) protoiface.SizeOutput { + x := input.Message.Interface().(*QueryLegacyAccountResponse) + if x == nil { + return protoiface.SizeOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Size: 0, + } + } + options := runtime.SizeInputToOptions(input) + _ = options + var n int + var l int + _ = l + if x.Account != nil { + l = options.Size(x.Account) + n += 1 + l + runtime.Sov(uint64(l)) + } + if x.Base != nil { + l = options.Size(x.Base) + n += 1 + l + runtime.Sov(uint64(l)) + } + if x.unknownFields != nil { + n += len(x.unknownFields) + } + return protoiface.SizeOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Size: n, + } + } + + marshal := func(input protoiface.MarshalInput) (protoiface.MarshalOutput, error) { + x := input.Message.Interface().(*QueryLegacyAccountResponse) + if x == nil { + return protoiface.MarshalOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Buf: input.Buf, + }, nil + } + options := runtime.MarshalInputToOptions(input) + _ = options + size := options.Size(x) + dAtA := make([]byte, size) + i := len(dAtA) + _ = i + var l int + _ = l + if x.unknownFields != nil { + i -= len(x.unknownFields) + copy(dAtA[i:], x.unknownFields) + } + if x.Base != nil { + encoded, err := options.Marshal(x.Base) + if err != nil { + return protoiface.MarshalOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Buf: input.Buf, + }, err + } + i -= len(encoded) + copy(dAtA[i:], encoded) + i = runtime.EncodeVarint(dAtA, i, uint64(len(encoded))) + i-- + dAtA[i] = 0x12 + } + if x.Account != nil { + encoded, err := options.Marshal(x.Account) + if err != nil { + return protoiface.MarshalOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Buf: input.Buf, + }, err + } + i -= len(encoded) + copy(dAtA[i:], encoded) + i = runtime.EncodeVarint(dAtA, i, uint64(len(encoded))) + i-- + dAtA[i] = 0xa + } + if input.Buf != nil { + input.Buf = append(input.Buf, dAtA...) + } else { + input.Buf = dAtA + } + return protoiface.MarshalOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Buf: input.Buf, + }, nil + } + unmarshal := func(input protoiface.UnmarshalInput) (protoiface.UnmarshalOutput, error) { + x := input.Message.Interface().(*QueryLegacyAccountResponse) + if x == nil { + return protoiface.UnmarshalOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Flags: input.Flags, + }, nil + } + options := runtime.UnmarshalInputToOptions(input) + _ = options + dAtA := input.Buf + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow + } + if iNdEx >= l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, 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 protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: QueryLegacyAccountResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: QueryLegacyAccountResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field Account", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow + } + if iNdEx >= l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + if postIndex > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + if x.Account == nil { + x.Account = &anypb.Any{} + } + if err := options.Unmarshal(dAtA[iNdEx:postIndex], x.Account); err != nil { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field Base", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow + } + if iNdEx >= l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + if postIndex > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + if x.Base == nil { + x.Base = &BaseAccount{} + } + if err := options.Unmarshal(dAtA[iNdEx:postIndex], x.Base); err != nil { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := runtime.Skip(dAtA[iNdEx:]) + if err != nil { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + if (iNdEx + skippy) > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + if !options.DiscardUnknown { + x.unknownFields = append(x.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + } + iNdEx += skippy + } + } + + if iNdEx > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, nil + } + return &protoiface.Methods{ + NoUnkeyedLiterals: struct{}{}, + Flags: protoiface.SupportMarshalDeterministic | protoiface.SupportUnmarshalDiscardUnknown, + Size: size, + Marshal: marshal, + Unmarshal: unmarshal, + Merge: nil, + CheckInitialized: nil, + } +} + +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.27.0 +// protoc (unknown) +// source: cosmos/auth/v1beta1/accounts.proto + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// QueryLegacyAccount defines a query that can be implemented by an x/account +// to return an auth understandable representation of an account. +// This query is only used for accounts retro-compatibility at gRPC +// level, the state machine must not make any assumptions around this. +type QueryLegacyAccount struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *QueryLegacyAccount) Reset() { + *x = QueryLegacyAccount{} + if protoimpl.UnsafeEnabled { + mi := &file_cosmos_auth_v1beta1_accounts_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *QueryLegacyAccount) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*QueryLegacyAccount) ProtoMessage() {} + +// Deprecated: Use QueryLegacyAccount.ProtoReflect.Descriptor instead. +func (*QueryLegacyAccount) Descriptor() ([]byte, []int) { + return file_cosmos_auth_v1beta1_accounts_proto_rawDescGZIP(), []int{0} +} + +// QueryLegacyAccountResponse defines the response type of the +// `QueryLegacyAccount` query. +type QueryLegacyAccountResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // account represents the google.Protobuf.Any wrapped account + // the type wrapped by the any does not need to comply with the + // sdk.AccountI interface. + Account *anypb.Any `protobuf:"bytes,1,opt,name=account,proto3" json:"account,omitempty"` + // base represents the account as a BaseAccount, this can return + // nil if the account cannot be represented as a BaseAccount. + // This is used in the gRPC QueryAccountInfo method. + Base *BaseAccount `protobuf:"bytes,2,opt,name=base,proto3" json:"base,omitempty"` +} + +func (x *QueryLegacyAccountResponse) Reset() { + *x = QueryLegacyAccountResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_cosmos_auth_v1beta1_accounts_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *QueryLegacyAccountResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*QueryLegacyAccountResponse) ProtoMessage() {} + +// Deprecated: Use QueryLegacyAccountResponse.ProtoReflect.Descriptor instead. +func (*QueryLegacyAccountResponse) Descriptor() ([]byte, []int) { + return file_cosmos_auth_v1beta1_accounts_proto_rawDescGZIP(), []int{1} +} + +func (x *QueryLegacyAccountResponse) GetAccount() *anypb.Any { + if x != nil { + return x.Account + } + return nil +} + +func (x *QueryLegacyAccountResponse) GetBase() *BaseAccount { + if x != nil { + return x.Base + } + return nil +} + +var File_cosmos_auth_v1beta1_accounts_proto protoreflect.FileDescriptor + +var file_cosmos_auth_v1beta1_accounts_proto_rawDesc = []byte{ + 0x0a, 0x22, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x61, 0x75, 0x74, 0x68, 0x2f, 0x76, 0x31, + 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x13, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x75, 0x74, + 0x68, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x1a, 0x19, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x61, 0x6e, 0x79, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x61, 0x75, 0x74, + 0x68, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x61, 0x75, 0x74, 0x68, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x14, 0x0a, 0x12, 0x51, 0x75, 0x65, 0x72, 0x79, 0x4c, 0x65, 0x67, + 0x61, 0x63, 0x79, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x82, 0x01, 0x0a, 0x1a, 0x51, + 0x75, 0x65, 0x72, 0x79, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, + 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2e, 0x0a, 0x07, 0x61, 0x63, 0x63, + 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, + 0x52, 0x07, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x34, 0x0a, 0x04, 0x62, 0x61, 0x73, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, + 0x2e, 0x61, 0x75, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x42, 0x61, + 0x73, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x04, 0x62, 0x61, 0x73, 0x65, 0x42, + 0xc8, 0x01, 0x0a, 0x17, 0x63, 0x6f, 0x6d, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x61, + 0x75, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x42, 0x0d, 0x41, 0x63, 0x63, + 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x30, 0x63, 0x6f, + 0x73, 0x6d, 0x6f, 0x73, 0x73, 0x64, 0x6b, 0x2e, 0x69, 0x6f, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x63, + 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x61, 0x75, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, + 0x61, 0x31, 0x3b, 0x61, 0x75, 0x74, 0x68, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0xa2, 0x02, + 0x03, 0x43, 0x41, 0x58, 0xaa, 0x02, 0x13, 0x43, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x75, + 0x74, 0x68, 0x2e, 0x56, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0xca, 0x02, 0x13, 0x43, 0x6f, 0x73, + 0x6d, 0x6f, 0x73, 0x5c, 0x41, 0x75, 0x74, 0x68, 0x5c, 0x56, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, + 0xe2, 0x02, 0x1f, 0x43, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x5c, 0x41, 0x75, 0x74, 0x68, 0x5c, 0x56, + 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, + 0x74, 0x61, 0xea, 0x02, 0x15, 0x43, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x3a, 0x3a, 0x41, 0x75, 0x74, + 0x68, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x33, +} + +var ( + file_cosmos_auth_v1beta1_accounts_proto_rawDescOnce sync.Once + file_cosmos_auth_v1beta1_accounts_proto_rawDescData = file_cosmos_auth_v1beta1_accounts_proto_rawDesc +) + +func file_cosmos_auth_v1beta1_accounts_proto_rawDescGZIP() []byte { + file_cosmos_auth_v1beta1_accounts_proto_rawDescOnce.Do(func() { + file_cosmos_auth_v1beta1_accounts_proto_rawDescData = protoimpl.X.CompressGZIP(file_cosmos_auth_v1beta1_accounts_proto_rawDescData) + }) + return file_cosmos_auth_v1beta1_accounts_proto_rawDescData +} + +var file_cosmos_auth_v1beta1_accounts_proto_msgTypes = make([]protoimpl.MessageInfo, 2) +var file_cosmos_auth_v1beta1_accounts_proto_goTypes = []interface{}{ + (*QueryLegacyAccount)(nil), // 0: cosmos.auth.v1beta1.QueryLegacyAccount + (*QueryLegacyAccountResponse)(nil), // 1: cosmos.auth.v1beta1.QueryLegacyAccountResponse + (*anypb.Any)(nil), // 2: google.protobuf.Any + (*BaseAccount)(nil), // 3: cosmos.auth.v1beta1.BaseAccount +} +var file_cosmos_auth_v1beta1_accounts_proto_depIdxs = []int32{ + 2, // 0: cosmos.auth.v1beta1.QueryLegacyAccountResponse.account:type_name -> google.protobuf.Any + 3, // 1: cosmos.auth.v1beta1.QueryLegacyAccountResponse.base:type_name -> cosmos.auth.v1beta1.BaseAccount + 2, // [2:2] is the sub-list for method output_type + 2, // [2:2] is the sub-list for method input_type + 2, // [2:2] is the sub-list for extension type_name + 2, // [2:2] is the sub-list for extension extendee + 0, // [0:2] is the sub-list for field type_name +} + +func init() { file_cosmos_auth_v1beta1_accounts_proto_init() } +func file_cosmos_auth_v1beta1_accounts_proto_init() { + if File_cosmos_auth_v1beta1_accounts_proto != nil { + return + } + file_cosmos_auth_v1beta1_auth_proto_init() + if !protoimpl.UnsafeEnabled { + file_cosmos_auth_v1beta1_accounts_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*QueryLegacyAccount); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cosmos_auth_v1beta1_accounts_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*QueryLegacyAccountResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_cosmos_auth_v1beta1_accounts_proto_rawDesc, + NumEnums: 0, + NumMessages: 2, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_cosmos_auth_v1beta1_accounts_proto_goTypes, + DependencyIndexes: file_cosmos_auth_v1beta1_accounts_proto_depIdxs, + MessageInfos: file_cosmos_auth_v1beta1_accounts_proto_msgTypes, + }.Build() + File_cosmos_auth_v1beta1_accounts_proto = out.File + file_cosmos_auth_v1beta1_accounts_proto_rawDesc = nil + file_cosmos_auth_v1beta1_accounts_proto_goTypes = nil + file_cosmos_auth_v1beta1_accounts_proto_depIdxs = nil +} diff --git a/api/cosmos/auth/v1beta1/tx.pulsar.go b/api/cosmos/auth/v1beta1/tx.pulsar.go index 429e8e3e437c..ff90234d44da 100644 --- a/api/cosmos/auth/v1beta1/tx.pulsar.go +++ b/api/cosmos/auth/v1beta1/tx.pulsar.go @@ -2423,6 +2423,1004 @@ func (x *fastReflection_MsgNonAtomicExecResponse) ProtoMethods() *protoiface.Met } } +var ( + md_MsgMigrateAccount protoreflect.MessageDescriptor + fd_MsgMigrateAccount_signer protoreflect.FieldDescriptor + fd_MsgMigrateAccount_account_type protoreflect.FieldDescriptor + fd_MsgMigrateAccount_account_init_msg protoreflect.FieldDescriptor +) + +func init() { + file_cosmos_auth_v1beta1_tx_proto_init() + md_MsgMigrateAccount = File_cosmos_auth_v1beta1_tx_proto.Messages().ByName("MsgMigrateAccount") + fd_MsgMigrateAccount_signer = md_MsgMigrateAccount.Fields().ByName("signer") + fd_MsgMigrateAccount_account_type = md_MsgMigrateAccount.Fields().ByName("account_type") + fd_MsgMigrateAccount_account_init_msg = md_MsgMigrateAccount.Fields().ByName("account_init_msg") +} + +var _ protoreflect.Message = (*fastReflection_MsgMigrateAccount)(nil) + +type fastReflection_MsgMigrateAccount MsgMigrateAccount + +func (x *MsgMigrateAccount) ProtoReflect() protoreflect.Message { + return (*fastReflection_MsgMigrateAccount)(x) +} + +func (x *MsgMigrateAccount) slowProtoReflect() protoreflect.Message { + mi := &file_cosmos_auth_v1beta1_tx_proto_msgTypes[5] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +var _fastReflection_MsgMigrateAccount_messageType fastReflection_MsgMigrateAccount_messageType +var _ protoreflect.MessageType = fastReflection_MsgMigrateAccount_messageType{} + +type fastReflection_MsgMigrateAccount_messageType struct{} + +func (x fastReflection_MsgMigrateAccount_messageType) Zero() protoreflect.Message { + return (*fastReflection_MsgMigrateAccount)(nil) +} +func (x fastReflection_MsgMigrateAccount_messageType) New() protoreflect.Message { + return new(fastReflection_MsgMigrateAccount) +} +func (x fastReflection_MsgMigrateAccount_messageType) Descriptor() protoreflect.MessageDescriptor { + return md_MsgMigrateAccount +} + +// Descriptor returns message descriptor, which contains only the protobuf +// type information for the message. +func (x *fastReflection_MsgMigrateAccount) Descriptor() protoreflect.MessageDescriptor { + return md_MsgMigrateAccount +} + +// Type returns the message type, which encapsulates both Go and protobuf +// type information. If the Go type information is not needed, +// it is recommended that the message descriptor be used instead. +func (x *fastReflection_MsgMigrateAccount) Type() protoreflect.MessageType { + return _fastReflection_MsgMigrateAccount_messageType +} + +// New returns a newly allocated and mutable empty message. +func (x *fastReflection_MsgMigrateAccount) New() protoreflect.Message { + return new(fastReflection_MsgMigrateAccount) +} + +// Interface unwraps the message reflection interface and +// returns the underlying ProtoMessage interface. +func (x *fastReflection_MsgMigrateAccount) Interface() protoreflect.ProtoMessage { + return (*MsgMigrateAccount)(x) +} + +// Range iterates over every populated field in an undefined order, +// calling f for each field descriptor and value encountered. +// Range returns immediately if f returns false. +// While iterating, mutating operations may only be performed +// on the current field descriptor. +func (x *fastReflection_MsgMigrateAccount) Range(f func(protoreflect.FieldDescriptor, protoreflect.Value) bool) { + if x.Signer != "" { + value := protoreflect.ValueOfString(x.Signer) + if !f(fd_MsgMigrateAccount_signer, value) { + return + } + } + if x.AccountType != "" { + value := protoreflect.ValueOfString(x.AccountType) + if !f(fd_MsgMigrateAccount_account_type, value) { + return + } + } + if x.AccountInitMsg != nil { + value := protoreflect.ValueOfMessage(x.AccountInitMsg.ProtoReflect()) + if !f(fd_MsgMigrateAccount_account_init_msg, value) { + return + } + } +} + +// Has reports whether a field is populated. +// +// Some fields have the property of nullability where it is possible to +// distinguish between the default value of a field and whether the field +// was explicitly populated with the default value. Singular message fields, +// member fields of a oneof, and proto2 scalar fields are nullable. Such +// fields are populated only if explicitly set. +// +// In other cases (aside from the nullable cases above), +// a proto3 scalar field is populated if it contains a non-zero value, and +// a repeated field is populated if it is non-empty. +func (x *fastReflection_MsgMigrateAccount) Has(fd protoreflect.FieldDescriptor) bool { + switch fd.FullName() { + case "cosmos.auth.v1beta1.MsgMigrateAccount.signer": + return x.Signer != "" + case "cosmos.auth.v1beta1.MsgMigrateAccount.account_type": + return x.AccountType != "" + case "cosmos.auth.v1beta1.MsgMigrateAccount.account_init_msg": + return x.AccountInitMsg != nil + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.auth.v1beta1.MsgMigrateAccount")) + } + panic(fmt.Errorf("message cosmos.auth.v1beta1.MsgMigrateAccount does not contain field %s", fd.FullName())) + } +} + +// Clear clears the field such that a subsequent Has call reports false. +// +// Clearing an extension field clears both the extension type and value +// associated with the given field number. +// +// Clear is a mutating operation and unsafe for concurrent use. +func (x *fastReflection_MsgMigrateAccount) Clear(fd protoreflect.FieldDescriptor) { + switch fd.FullName() { + case "cosmos.auth.v1beta1.MsgMigrateAccount.signer": + x.Signer = "" + case "cosmos.auth.v1beta1.MsgMigrateAccount.account_type": + x.AccountType = "" + case "cosmos.auth.v1beta1.MsgMigrateAccount.account_init_msg": + x.AccountInitMsg = nil + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.auth.v1beta1.MsgMigrateAccount")) + } + panic(fmt.Errorf("message cosmos.auth.v1beta1.MsgMigrateAccount does not contain field %s", fd.FullName())) + } +} + +// Get retrieves the value for a field. +// +// For unpopulated scalars, it returns the default value, where +// the default value of a bytes scalar is guaranteed to be a copy. +// For unpopulated composite types, it returns an empty, read-only view +// of the value; to obtain a mutable reference, use Mutable. +func (x *fastReflection_MsgMigrateAccount) Get(descriptor protoreflect.FieldDescriptor) protoreflect.Value { + switch descriptor.FullName() { + case "cosmos.auth.v1beta1.MsgMigrateAccount.signer": + value := x.Signer + return protoreflect.ValueOfString(value) + case "cosmos.auth.v1beta1.MsgMigrateAccount.account_type": + value := x.AccountType + return protoreflect.ValueOfString(value) + case "cosmos.auth.v1beta1.MsgMigrateAccount.account_init_msg": + value := x.AccountInitMsg + return protoreflect.ValueOfMessage(value.ProtoReflect()) + default: + if descriptor.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.auth.v1beta1.MsgMigrateAccount")) + } + panic(fmt.Errorf("message cosmos.auth.v1beta1.MsgMigrateAccount does not contain field %s", descriptor.FullName())) + } +} + +// Set stores the value for a field. +// +// For a field belonging to a oneof, it implicitly clears any other field +// that may be currently set within the same oneof. +// For extension fields, it implicitly stores the provided ExtensionType. +// When setting a composite type, it is unspecified whether the stored value +// aliases the source's memory in any way. If the composite value is an +// empty, read-only value, then it panics. +// +// Set is a mutating operation and unsafe for concurrent use. +func (x *fastReflection_MsgMigrateAccount) Set(fd protoreflect.FieldDescriptor, value protoreflect.Value) { + switch fd.FullName() { + case "cosmos.auth.v1beta1.MsgMigrateAccount.signer": + x.Signer = value.Interface().(string) + case "cosmos.auth.v1beta1.MsgMigrateAccount.account_type": + x.AccountType = value.Interface().(string) + case "cosmos.auth.v1beta1.MsgMigrateAccount.account_init_msg": + x.AccountInitMsg = value.Message().Interface().(*anypb.Any) + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.auth.v1beta1.MsgMigrateAccount")) + } + panic(fmt.Errorf("message cosmos.auth.v1beta1.MsgMigrateAccount does not contain field %s", fd.FullName())) + } +} + +// Mutable returns a mutable reference to a composite type. +// +// If the field is unpopulated, it may allocate a composite value. +// For a field belonging to a oneof, it implicitly clears any other field +// that may be currently set within the same oneof. +// For extension fields, it implicitly stores the provided ExtensionType +// if not already stored. +// It panics if the field does not contain a composite type. +// +// Mutable is a mutating operation and unsafe for concurrent use. +func (x *fastReflection_MsgMigrateAccount) Mutable(fd protoreflect.FieldDescriptor) protoreflect.Value { + switch fd.FullName() { + case "cosmos.auth.v1beta1.MsgMigrateAccount.account_init_msg": + if x.AccountInitMsg == nil { + x.AccountInitMsg = new(anypb.Any) + } + return protoreflect.ValueOfMessage(x.AccountInitMsg.ProtoReflect()) + case "cosmos.auth.v1beta1.MsgMigrateAccount.signer": + panic(fmt.Errorf("field signer of message cosmos.auth.v1beta1.MsgMigrateAccount is not mutable")) + case "cosmos.auth.v1beta1.MsgMigrateAccount.account_type": + panic(fmt.Errorf("field account_type of message cosmos.auth.v1beta1.MsgMigrateAccount is not mutable")) + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.auth.v1beta1.MsgMigrateAccount")) + } + panic(fmt.Errorf("message cosmos.auth.v1beta1.MsgMigrateAccount does not contain field %s", fd.FullName())) + } +} + +// NewField returns a new value that is assignable to the field +// for the given descriptor. For scalars, this returns the default value. +// For lists, maps, and messages, this returns a new, empty, mutable value. +func (x *fastReflection_MsgMigrateAccount) NewField(fd protoreflect.FieldDescriptor) protoreflect.Value { + switch fd.FullName() { + case "cosmos.auth.v1beta1.MsgMigrateAccount.signer": + return protoreflect.ValueOfString("") + case "cosmos.auth.v1beta1.MsgMigrateAccount.account_type": + return protoreflect.ValueOfString("") + case "cosmos.auth.v1beta1.MsgMigrateAccount.account_init_msg": + m := new(anypb.Any) + return protoreflect.ValueOfMessage(m.ProtoReflect()) + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.auth.v1beta1.MsgMigrateAccount")) + } + panic(fmt.Errorf("message cosmos.auth.v1beta1.MsgMigrateAccount does not contain field %s", fd.FullName())) + } +} + +// WhichOneof reports which field within the oneof is populated, +// returning nil if none are populated. +// It panics if the oneof descriptor does not belong to this message. +func (x *fastReflection_MsgMigrateAccount) WhichOneof(d protoreflect.OneofDescriptor) protoreflect.FieldDescriptor { + switch d.FullName() { + default: + panic(fmt.Errorf("%s is not a oneof field in cosmos.auth.v1beta1.MsgMigrateAccount", d.FullName())) + } + panic("unreachable") +} + +// GetUnknown retrieves the entire list of unknown fields. +// The caller may only mutate the contents of the RawFields +// if the mutated bytes are stored back into the message with SetUnknown. +func (x *fastReflection_MsgMigrateAccount) GetUnknown() protoreflect.RawFields { + return x.unknownFields +} + +// SetUnknown stores an entire list of unknown fields. +// The raw fields must be syntactically valid according to the wire format. +// An implementation may panic if this is not the case. +// Once stored, the caller must not mutate the content of the RawFields. +// An empty RawFields may be passed to clear the fields. +// +// SetUnknown is a mutating operation and unsafe for concurrent use. +func (x *fastReflection_MsgMigrateAccount) SetUnknown(fields protoreflect.RawFields) { + x.unknownFields = fields +} + +// IsValid reports whether the message is valid. +// +// An invalid message is an empty, read-only value. +// +// An invalid message often corresponds to a nil pointer of the concrete +// message type, but the details are implementation dependent. +// Validity is not part of the protobuf data model, and may not +// be preserved in marshaling or other operations. +func (x *fastReflection_MsgMigrateAccount) IsValid() bool { + return x != nil +} + +// ProtoMethods returns optional fastReflectionFeature-path implementations of various operations. +// This method may return nil. +// +// The returned methods type is identical to +// "google.golang.org/protobuf/runtime/protoiface".Methods. +// Consult the protoiface package documentation for details. +func (x *fastReflection_MsgMigrateAccount) ProtoMethods() *protoiface.Methods { + size := func(input protoiface.SizeInput) protoiface.SizeOutput { + x := input.Message.Interface().(*MsgMigrateAccount) + if x == nil { + return protoiface.SizeOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Size: 0, + } + } + options := runtime.SizeInputToOptions(input) + _ = options + var n int + var l int + _ = l + l = len(x.Signer) + if l > 0 { + n += 1 + l + runtime.Sov(uint64(l)) + } + l = len(x.AccountType) + if l > 0 { + n += 1 + l + runtime.Sov(uint64(l)) + } + if x.AccountInitMsg != nil { + l = options.Size(x.AccountInitMsg) + n += 1 + l + runtime.Sov(uint64(l)) + } + if x.unknownFields != nil { + n += len(x.unknownFields) + } + return protoiface.SizeOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Size: n, + } + } + + marshal := func(input protoiface.MarshalInput) (protoiface.MarshalOutput, error) { + x := input.Message.Interface().(*MsgMigrateAccount) + if x == nil { + return protoiface.MarshalOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Buf: input.Buf, + }, nil + } + options := runtime.MarshalInputToOptions(input) + _ = options + size := options.Size(x) + dAtA := make([]byte, size) + i := len(dAtA) + _ = i + var l int + _ = l + if x.unknownFields != nil { + i -= len(x.unknownFields) + copy(dAtA[i:], x.unknownFields) + } + if x.AccountInitMsg != nil { + encoded, err := options.Marshal(x.AccountInitMsg) + if err != nil { + return protoiface.MarshalOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Buf: input.Buf, + }, err + } + i -= len(encoded) + copy(dAtA[i:], encoded) + i = runtime.EncodeVarint(dAtA, i, uint64(len(encoded))) + i-- + dAtA[i] = 0x1a + } + if len(x.AccountType) > 0 { + i -= len(x.AccountType) + copy(dAtA[i:], x.AccountType) + i = runtime.EncodeVarint(dAtA, i, uint64(len(x.AccountType))) + i-- + dAtA[i] = 0x12 + } + if len(x.Signer) > 0 { + i -= len(x.Signer) + copy(dAtA[i:], x.Signer) + i = runtime.EncodeVarint(dAtA, i, uint64(len(x.Signer))) + i-- + dAtA[i] = 0xa + } + if input.Buf != nil { + input.Buf = append(input.Buf, dAtA...) + } else { + input.Buf = dAtA + } + return protoiface.MarshalOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Buf: input.Buf, + }, nil + } + unmarshal := func(input protoiface.UnmarshalInput) (protoiface.UnmarshalOutput, error) { + x := input.Message.Interface().(*MsgMigrateAccount) + if x == nil { + return protoiface.UnmarshalOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Flags: input.Flags, + }, nil + } + options := runtime.UnmarshalInputToOptions(input) + _ = options + dAtA := input.Buf + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow + } + if iNdEx >= l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, 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 protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: MsgMigrateAccount: wiretype end group for non-group") + } + if fieldNum <= 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: MsgMigrateAccount: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field Signer", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow + } + if iNdEx >= l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + if postIndex > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + x.Signer = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field AccountType", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow + } + if iNdEx >= l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + if postIndex > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + x.AccountType = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field AccountInitMsg", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow + } + if iNdEx >= l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + if postIndex > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + if x.AccountInitMsg == nil { + x.AccountInitMsg = &anypb.Any{} + } + if err := options.Unmarshal(dAtA[iNdEx:postIndex], x.AccountInitMsg); err != nil { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := runtime.Skip(dAtA[iNdEx:]) + if err != nil { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + if (iNdEx + skippy) > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + if !options.DiscardUnknown { + x.unknownFields = append(x.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + } + iNdEx += skippy + } + } + + if iNdEx > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, nil + } + return &protoiface.Methods{ + NoUnkeyedLiterals: struct{}{}, + Flags: protoiface.SupportMarshalDeterministic | protoiface.SupportUnmarshalDiscardUnknown, + Size: size, + Marshal: marshal, + Unmarshal: unmarshal, + Merge: nil, + CheckInitialized: nil, + } +} + +var ( + md_MsgMigrateAccountResponse protoreflect.MessageDescriptor + fd_MsgMigrateAccountResponse_init_response protoreflect.FieldDescriptor +) + +func init() { + file_cosmos_auth_v1beta1_tx_proto_init() + md_MsgMigrateAccountResponse = File_cosmos_auth_v1beta1_tx_proto.Messages().ByName("MsgMigrateAccountResponse") + fd_MsgMigrateAccountResponse_init_response = md_MsgMigrateAccountResponse.Fields().ByName("init_response") +} + +var _ protoreflect.Message = (*fastReflection_MsgMigrateAccountResponse)(nil) + +type fastReflection_MsgMigrateAccountResponse MsgMigrateAccountResponse + +func (x *MsgMigrateAccountResponse) ProtoReflect() protoreflect.Message { + return (*fastReflection_MsgMigrateAccountResponse)(x) +} + +func (x *MsgMigrateAccountResponse) slowProtoReflect() protoreflect.Message { + mi := &file_cosmos_auth_v1beta1_tx_proto_msgTypes[6] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +var _fastReflection_MsgMigrateAccountResponse_messageType fastReflection_MsgMigrateAccountResponse_messageType +var _ protoreflect.MessageType = fastReflection_MsgMigrateAccountResponse_messageType{} + +type fastReflection_MsgMigrateAccountResponse_messageType struct{} + +func (x fastReflection_MsgMigrateAccountResponse_messageType) Zero() protoreflect.Message { + return (*fastReflection_MsgMigrateAccountResponse)(nil) +} +func (x fastReflection_MsgMigrateAccountResponse_messageType) New() protoreflect.Message { + return new(fastReflection_MsgMigrateAccountResponse) +} +func (x fastReflection_MsgMigrateAccountResponse_messageType) Descriptor() protoreflect.MessageDescriptor { + return md_MsgMigrateAccountResponse +} + +// Descriptor returns message descriptor, which contains only the protobuf +// type information for the message. +func (x *fastReflection_MsgMigrateAccountResponse) Descriptor() protoreflect.MessageDescriptor { + return md_MsgMigrateAccountResponse +} + +// Type returns the message type, which encapsulates both Go and protobuf +// type information. If the Go type information is not needed, +// it is recommended that the message descriptor be used instead. +func (x *fastReflection_MsgMigrateAccountResponse) Type() protoreflect.MessageType { + return _fastReflection_MsgMigrateAccountResponse_messageType +} + +// New returns a newly allocated and mutable empty message. +func (x *fastReflection_MsgMigrateAccountResponse) New() protoreflect.Message { + return new(fastReflection_MsgMigrateAccountResponse) +} + +// Interface unwraps the message reflection interface and +// returns the underlying ProtoMessage interface. +func (x *fastReflection_MsgMigrateAccountResponse) Interface() protoreflect.ProtoMessage { + return (*MsgMigrateAccountResponse)(x) +} + +// Range iterates over every populated field in an undefined order, +// calling f for each field descriptor and value encountered. +// Range returns immediately if f returns false. +// While iterating, mutating operations may only be performed +// on the current field descriptor. +func (x *fastReflection_MsgMigrateAccountResponse) Range(f func(protoreflect.FieldDescriptor, protoreflect.Value) bool) { + if x.InitResponse != nil { + value := protoreflect.ValueOfMessage(x.InitResponse.ProtoReflect()) + if !f(fd_MsgMigrateAccountResponse_init_response, value) { + return + } + } +} + +// Has reports whether a field is populated. +// +// Some fields have the property of nullability where it is possible to +// distinguish between the default value of a field and whether the field +// was explicitly populated with the default value. Singular message fields, +// member fields of a oneof, and proto2 scalar fields are nullable. Such +// fields are populated only if explicitly set. +// +// In other cases (aside from the nullable cases above), +// a proto3 scalar field is populated if it contains a non-zero value, and +// a repeated field is populated if it is non-empty. +func (x *fastReflection_MsgMigrateAccountResponse) Has(fd protoreflect.FieldDescriptor) bool { + switch fd.FullName() { + case "cosmos.auth.v1beta1.MsgMigrateAccountResponse.init_response": + return x.InitResponse != nil + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.auth.v1beta1.MsgMigrateAccountResponse")) + } + panic(fmt.Errorf("message cosmos.auth.v1beta1.MsgMigrateAccountResponse does not contain field %s", fd.FullName())) + } +} + +// Clear clears the field such that a subsequent Has call reports false. +// +// Clearing an extension field clears both the extension type and value +// associated with the given field number. +// +// Clear is a mutating operation and unsafe for concurrent use. +func (x *fastReflection_MsgMigrateAccountResponse) Clear(fd protoreflect.FieldDescriptor) { + switch fd.FullName() { + case "cosmos.auth.v1beta1.MsgMigrateAccountResponse.init_response": + x.InitResponse = nil + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.auth.v1beta1.MsgMigrateAccountResponse")) + } + panic(fmt.Errorf("message cosmos.auth.v1beta1.MsgMigrateAccountResponse does not contain field %s", fd.FullName())) + } +} + +// Get retrieves the value for a field. +// +// For unpopulated scalars, it returns the default value, where +// the default value of a bytes scalar is guaranteed to be a copy. +// For unpopulated composite types, it returns an empty, read-only view +// of the value; to obtain a mutable reference, use Mutable. +func (x *fastReflection_MsgMigrateAccountResponse) Get(descriptor protoreflect.FieldDescriptor) protoreflect.Value { + switch descriptor.FullName() { + case "cosmos.auth.v1beta1.MsgMigrateAccountResponse.init_response": + value := x.InitResponse + return protoreflect.ValueOfMessage(value.ProtoReflect()) + default: + if descriptor.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.auth.v1beta1.MsgMigrateAccountResponse")) + } + panic(fmt.Errorf("message cosmos.auth.v1beta1.MsgMigrateAccountResponse does not contain field %s", descriptor.FullName())) + } +} + +// Set stores the value for a field. +// +// For a field belonging to a oneof, it implicitly clears any other field +// that may be currently set within the same oneof. +// For extension fields, it implicitly stores the provided ExtensionType. +// When setting a composite type, it is unspecified whether the stored value +// aliases the source's memory in any way. If the composite value is an +// empty, read-only value, then it panics. +// +// Set is a mutating operation and unsafe for concurrent use. +func (x *fastReflection_MsgMigrateAccountResponse) Set(fd protoreflect.FieldDescriptor, value protoreflect.Value) { + switch fd.FullName() { + case "cosmos.auth.v1beta1.MsgMigrateAccountResponse.init_response": + x.InitResponse = value.Message().Interface().(*anypb.Any) + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.auth.v1beta1.MsgMigrateAccountResponse")) + } + panic(fmt.Errorf("message cosmos.auth.v1beta1.MsgMigrateAccountResponse does not contain field %s", fd.FullName())) + } +} + +// Mutable returns a mutable reference to a composite type. +// +// If the field is unpopulated, it may allocate a composite value. +// For a field belonging to a oneof, it implicitly clears any other field +// that may be currently set within the same oneof. +// For extension fields, it implicitly stores the provided ExtensionType +// if not already stored. +// It panics if the field does not contain a composite type. +// +// Mutable is a mutating operation and unsafe for concurrent use. +func (x *fastReflection_MsgMigrateAccountResponse) Mutable(fd protoreflect.FieldDescriptor) protoreflect.Value { + switch fd.FullName() { + case "cosmos.auth.v1beta1.MsgMigrateAccountResponse.init_response": + if x.InitResponse == nil { + x.InitResponse = new(anypb.Any) + } + return protoreflect.ValueOfMessage(x.InitResponse.ProtoReflect()) + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.auth.v1beta1.MsgMigrateAccountResponse")) + } + panic(fmt.Errorf("message cosmos.auth.v1beta1.MsgMigrateAccountResponse does not contain field %s", fd.FullName())) + } +} + +// NewField returns a new value that is assignable to the field +// for the given descriptor. For scalars, this returns the default value. +// For lists, maps, and messages, this returns a new, empty, mutable value. +func (x *fastReflection_MsgMigrateAccountResponse) NewField(fd protoreflect.FieldDescriptor) protoreflect.Value { + switch fd.FullName() { + case "cosmos.auth.v1beta1.MsgMigrateAccountResponse.init_response": + m := new(anypb.Any) + return protoreflect.ValueOfMessage(m.ProtoReflect()) + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.auth.v1beta1.MsgMigrateAccountResponse")) + } + panic(fmt.Errorf("message cosmos.auth.v1beta1.MsgMigrateAccountResponse does not contain field %s", fd.FullName())) + } +} + +// WhichOneof reports which field within the oneof is populated, +// returning nil if none are populated. +// It panics if the oneof descriptor does not belong to this message. +func (x *fastReflection_MsgMigrateAccountResponse) WhichOneof(d protoreflect.OneofDescriptor) protoreflect.FieldDescriptor { + switch d.FullName() { + default: + panic(fmt.Errorf("%s is not a oneof field in cosmos.auth.v1beta1.MsgMigrateAccountResponse", d.FullName())) + } + panic("unreachable") +} + +// GetUnknown retrieves the entire list of unknown fields. +// The caller may only mutate the contents of the RawFields +// if the mutated bytes are stored back into the message with SetUnknown. +func (x *fastReflection_MsgMigrateAccountResponse) GetUnknown() protoreflect.RawFields { + return x.unknownFields +} + +// SetUnknown stores an entire list of unknown fields. +// The raw fields must be syntactically valid according to the wire format. +// An implementation may panic if this is not the case. +// Once stored, the caller must not mutate the content of the RawFields. +// An empty RawFields may be passed to clear the fields. +// +// SetUnknown is a mutating operation and unsafe for concurrent use. +func (x *fastReflection_MsgMigrateAccountResponse) SetUnknown(fields protoreflect.RawFields) { + x.unknownFields = fields +} + +// IsValid reports whether the message is valid. +// +// An invalid message is an empty, read-only value. +// +// An invalid message often corresponds to a nil pointer of the concrete +// message type, but the details are implementation dependent. +// Validity is not part of the protobuf data model, and may not +// be preserved in marshaling or other operations. +func (x *fastReflection_MsgMigrateAccountResponse) IsValid() bool { + return x != nil +} + +// ProtoMethods returns optional fastReflectionFeature-path implementations of various operations. +// This method may return nil. +// +// The returned methods type is identical to +// "google.golang.org/protobuf/runtime/protoiface".Methods. +// Consult the protoiface package documentation for details. +func (x *fastReflection_MsgMigrateAccountResponse) ProtoMethods() *protoiface.Methods { + size := func(input protoiface.SizeInput) protoiface.SizeOutput { + x := input.Message.Interface().(*MsgMigrateAccountResponse) + if x == nil { + return protoiface.SizeOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Size: 0, + } + } + options := runtime.SizeInputToOptions(input) + _ = options + var n int + var l int + _ = l + if x.InitResponse != nil { + l = options.Size(x.InitResponse) + n += 1 + l + runtime.Sov(uint64(l)) + } + if x.unknownFields != nil { + n += len(x.unknownFields) + } + return protoiface.SizeOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Size: n, + } + } + + marshal := func(input protoiface.MarshalInput) (protoiface.MarshalOutput, error) { + x := input.Message.Interface().(*MsgMigrateAccountResponse) + if x == nil { + return protoiface.MarshalOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Buf: input.Buf, + }, nil + } + options := runtime.MarshalInputToOptions(input) + _ = options + size := options.Size(x) + dAtA := make([]byte, size) + i := len(dAtA) + _ = i + var l int + _ = l + if x.unknownFields != nil { + i -= len(x.unknownFields) + copy(dAtA[i:], x.unknownFields) + } + if x.InitResponse != nil { + encoded, err := options.Marshal(x.InitResponse) + if err != nil { + return protoiface.MarshalOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Buf: input.Buf, + }, err + } + i -= len(encoded) + copy(dAtA[i:], encoded) + i = runtime.EncodeVarint(dAtA, i, uint64(len(encoded))) + i-- + dAtA[i] = 0xa + } + if input.Buf != nil { + input.Buf = append(input.Buf, dAtA...) + } else { + input.Buf = dAtA + } + return protoiface.MarshalOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Buf: input.Buf, + }, nil + } + unmarshal := func(input protoiface.UnmarshalInput) (protoiface.UnmarshalOutput, error) { + x := input.Message.Interface().(*MsgMigrateAccountResponse) + if x == nil { + return protoiface.UnmarshalOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Flags: input.Flags, + }, nil + } + options := runtime.UnmarshalInputToOptions(input) + _ = options + dAtA := input.Buf + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow + } + if iNdEx >= l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, 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 protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: MsgMigrateAccountResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: MsgMigrateAccountResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field InitResponse", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow + } + if iNdEx >= l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + if postIndex > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + if x.InitResponse == nil { + x.InitResponse = &anypb.Any{} + } + if err := options.Unmarshal(dAtA[iNdEx:postIndex], x.InitResponse); err != nil { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := runtime.Skip(dAtA[iNdEx:]) + if err != nil { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + if (iNdEx + skippy) > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + if !options.DiscardUnknown { + x.unknownFields = append(x.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + } + iNdEx += skippy + } + } + + if iNdEx > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, nil + } + return &protoiface.Methods{ + NoUnkeyedLiterals: struct{}{}, + Flags: protoiface.SupportMarshalDeterministic | protoiface.SupportUnmarshalDiscardUnknown, + Size: size, + Marshal: marshal, + Unmarshal: unmarshal, + Merge: nil, + CheckInitialized: nil, + } +} + // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.27.0 @@ -2637,6 +3635,98 @@ func (x *MsgNonAtomicExecResponse) GetResults() []*NonAtomicExecResult { return nil } +// MsgMigrateAccount defines a message which allows users to migrate from BaseAccount +// to other x/accounts types. +type MsgMigrateAccount struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Signer string `protobuf:"bytes,1,opt,name=signer,proto3" json:"signer,omitempty"` + AccountType string `protobuf:"bytes,2,opt,name=account_type,json=accountType,proto3" json:"account_type,omitempty"` + AccountInitMsg *anypb.Any `protobuf:"bytes,3,opt,name=account_init_msg,json=accountInitMsg,proto3" json:"account_init_msg,omitempty"` +} + +func (x *MsgMigrateAccount) Reset() { + *x = MsgMigrateAccount{} + if protoimpl.UnsafeEnabled { + mi := &file_cosmos_auth_v1beta1_tx_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *MsgMigrateAccount) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MsgMigrateAccount) ProtoMessage() {} + +// Deprecated: Use MsgMigrateAccount.ProtoReflect.Descriptor instead. +func (*MsgMigrateAccount) Descriptor() ([]byte, []int) { + return file_cosmos_auth_v1beta1_tx_proto_rawDescGZIP(), []int{5} +} + +func (x *MsgMigrateAccount) GetSigner() string { + if x != nil { + return x.Signer + } + return "" +} + +func (x *MsgMigrateAccount) GetAccountType() string { + if x != nil { + return x.AccountType + } + return "" +} + +func (x *MsgMigrateAccount) GetAccountInitMsg() *anypb.Any { + if x != nil { + return x.AccountInitMsg + } + return nil +} + +// MsgMigrateAccountResponse defines the response given when migrating to +// an x/accounts account. +type MsgMigrateAccountResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // init_response defines the response returned by the x/account account + // initialization. + InitResponse *anypb.Any `protobuf:"bytes,1,opt,name=init_response,json=initResponse,proto3" json:"init_response,omitempty"` +} + +func (x *MsgMigrateAccountResponse) Reset() { + *x = MsgMigrateAccountResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_cosmos_auth_v1beta1_tx_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *MsgMigrateAccountResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MsgMigrateAccountResponse) ProtoMessage() {} + +// Deprecated: Use MsgMigrateAccountResponse.ProtoReflect.Descriptor instead. +func (*MsgMigrateAccountResponse) Descriptor() ([]byte, []int) { + return file_cosmos_auth_v1beta1_tx_proto_rawDescGZIP(), []int{6} +} + +func (x *MsgMigrateAccountResponse) GetInitResponse() *anypb.Any { + if x != nil { + return x.InitResponse + } + return nil +} + var File_cosmos_auth_v1beta1_tx_proto protoreflect.FileDescriptor var file_cosmos_auth_v1beta1_tx_proto_rawDesc = []byte{ @@ -2690,34 +3780,60 @@ var file_cosmos_auth_v1beta1_tx_proto_rawDesc = []byte{ 0x28, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x75, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x4e, 0x6f, 0x6e, 0x41, 0x74, 0x6f, 0x6d, 0x69, 0x63, 0x45, 0x78, 0x65, 0x63, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, - 0x74, 0x73, 0x32, 0xec, 0x01, 0x0a, 0x03, 0x4d, 0x73, 0x67, 0x12, 0x77, 0x0a, 0x0c, 0x55, 0x70, - 0x64, 0x61, 0x74, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x24, 0x2e, 0x63, 0x6f, 0x73, - 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x75, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x2e, 0x4d, 0x73, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, - 0x1a, 0x2c, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x75, 0x74, 0x68, 0x2e, 0x76, - 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, - 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x13, - 0xca, 0xb4, 0x2d, 0x0f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2d, 0x73, 0x64, 0x6b, 0x20, 0x30, - 0x2e, 0x34, 0x37, 0x12, 0x65, 0x0a, 0x0d, 0x4e, 0x6f, 0x6e, 0x41, 0x74, 0x6f, 0x6d, 0x69, 0x63, - 0x45, 0x78, 0x65, 0x63, 0x12, 0x25, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x75, - 0x74, 0x68, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x4e, 0x6f, - 0x6e, 0x41, 0x74, 0x6f, 0x6d, 0x69, 0x63, 0x45, 0x78, 0x65, 0x63, 0x1a, 0x2d, 0x2e, 0x63, 0x6f, - 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x75, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, - 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x4e, 0x6f, 0x6e, 0x41, 0x74, 0x6f, 0x6d, 0x69, 0x63, 0x45, 0x78, - 0x65, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x1a, 0x05, 0x80, 0xe7, 0xb0, 0x2a, - 0x01, 0x42, 0xc2, 0x01, 0x0a, 0x17, 0x63, 0x6f, 0x6d, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, - 0x2e, 0x61, 0x75, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x42, 0x07, 0x54, - 0x78, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x30, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, - 0x73, 0x64, 0x6b, 0x2e, 0x69, 0x6f, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, - 0x73, 0x2f, 0x61, 0x75, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x3b, 0x61, - 0x75, 0x74, 0x68, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0xa2, 0x02, 0x03, 0x43, 0x41, 0x58, - 0xaa, 0x02, 0x13, 0x43, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x2e, 0x56, - 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0xca, 0x02, 0x13, 0x43, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x5c, - 0x41, 0x75, 0x74, 0x68, 0x5c, 0x56, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0xe2, 0x02, 0x1f, 0x43, - 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x5c, 0x41, 0x75, 0x74, 0x68, 0x5c, 0x56, 0x31, 0x62, 0x65, 0x74, - 0x61, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, - 0x15, 0x43, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x3a, 0x3a, 0x41, 0x75, 0x74, 0x68, 0x3a, 0x3a, 0x56, - 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x74, 0x73, 0x22, 0xdd, 0x01, 0x0a, 0x11, 0x4d, 0x73, 0x67, 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, + 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x30, 0x0a, 0x06, 0x73, 0x69, 0x67, 0x6e, + 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xd2, 0xb4, 0x2d, 0x14, 0x63, 0x6f, + 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, 0x69, + 0x6e, 0x67, 0x52, 0x06, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x12, 0x21, 0x0a, 0x0c, 0x61, 0x63, + 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0b, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x3e, 0x0a, + 0x10, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x69, 0x6e, 0x69, 0x74, 0x5f, 0x6d, 0x73, + 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x52, 0x0e, 0x61, + 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x6e, 0x69, 0x74, 0x4d, 0x73, 0x67, 0x3a, 0x33, 0x82, + 0xe7, 0xb0, 0x2a, 0x06, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x8a, 0xe7, 0xb0, 0x2a, 0x23, 0x63, + 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2d, 0x73, 0x64, 0x6b, 0x2f, 0x78, 0x2f, 0x61, 0x75, 0x74, 0x68, + 0x2f, 0x4d, 0x73, 0x67, 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, + 0x6e, 0x74, 0x22, 0x56, 0x0a, 0x19, 0x4d, 0x73, 0x67, 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x65, + 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x39, 0x0a, 0x0d, 0x69, 0x6e, 0x69, 0x74, 0x5f, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x52, 0x0c, 0x69, 0x6e, + 0x69, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0xd6, 0x02, 0x0a, 0x03, 0x4d, + 0x73, 0x67, 0x12, 0x77, 0x0a, 0x0c, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x61, 0x72, 0x61, + 0x6d, 0x73, 0x12, 0x24, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x75, 0x74, 0x68, + 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x55, 0x70, 0x64, 0x61, + 0x74, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x1a, 0x2c, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, + 0x73, 0x2e, 0x61, 0x75, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x4d, + 0x73, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x13, 0xca, 0xb4, 0x2d, 0x0f, 0x63, 0x6f, 0x73, 0x6d, + 0x6f, 0x73, 0x2d, 0x73, 0x64, 0x6b, 0x20, 0x30, 0x2e, 0x34, 0x37, 0x12, 0x65, 0x0a, 0x0d, 0x4e, + 0x6f, 0x6e, 0x41, 0x74, 0x6f, 0x6d, 0x69, 0x63, 0x45, 0x78, 0x65, 0x63, 0x12, 0x25, 0x2e, 0x63, + 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x75, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, + 0x61, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x4e, 0x6f, 0x6e, 0x41, 0x74, 0x6f, 0x6d, 0x69, 0x63, 0x45, + 0x78, 0x65, 0x63, 0x1a, 0x2d, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x75, 0x74, + 0x68, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x4e, 0x6f, 0x6e, + 0x41, 0x74, 0x6f, 0x6d, 0x69, 0x63, 0x45, 0x78, 0x65, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x68, 0x0a, 0x0e, 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x65, 0x41, 0x63, 0x63, + 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x26, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x75, + 0x74, 0x68, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x4d, 0x69, + 0x67, 0x72, 0x61, 0x74, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x1a, 0x2e, 0x2e, 0x63, + 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x75, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, + 0x61, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x65, 0x41, 0x63, 0x63, + 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x1a, 0x05, 0x80, 0xe7, + 0xb0, 0x2a, 0x01, 0x42, 0xc2, 0x01, 0x0a, 0x17, 0x63, 0x6f, 0x6d, 0x2e, 0x63, 0x6f, 0x73, 0x6d, + 0x6f, 0x73, 0x2e, 0x61, 0x75, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x42, + 0x07, 0x54, 0x78, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x30, 0x63, 0x6f, 0x73, 0x6d, + 0x6f, 0x73, 0x73, 0x64, 0x6b, 0x2e, 0x69, 0x6f, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x63, 0x6f, 0x73, + 0x6d, 0x6f, 0x73, 0x2f, 0x61, 0x75, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, + 0x3b, 0x61, 0x75, 0x74, 0x68, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0xa2, 0x02, 0x03, 0x43, + 0x41, 0x58, 0xaa, 0x02, 0x13, 0x43, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x75, 0x74, 0x68, + 0x2e, 0x56, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0xca, 0x02, 0x13, 0x43, 0x6f, 0x73, 0x6d, 0x6f, + 0x73, 0x5c, 0x41, 0x75, 0x74, 0x68, 0x5c, 0x56, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0xe2, 0x02, + 0x1f, 0x43, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x5c, 0x41, 0x75, 0x74, 0x68, 0x5c, 0x56, 0x31, 0x62, + 0x65, 0x74, 0x61, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, + 0xea, 0x02, 0x15, 0x43, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x3a, 0x3a, 0x41, 0x75, 0x74, 0x68, 0x3a, + 0x3a, 0x56, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -2732,30 +3848,36 @@ func file_cosmos_auth_v1beta1_tx_proto_rawDescGZIP() []byte { return file_cosmos_auth_v1beta1_tx_proto_rawDescData } -var file_cosmos_auth_v1beta1_tx_proto_msgTypes = make([]protoimpl.MessageInfo, 5) +var file_cosmos_auth_v1beta1_tx_proto_msgTypes = make([]protoimpl.MessageInfo, 7) var file_cosmos_auth_v1beta1_tx_proto_goTypes = []interface{}{ - (*MsgUpdateParams)(nil), // 0: cosmos.auth.v1beta1.MsgUpdateParams - (*MsgUpdateParamsResponse)(nil), // 1: cosmos.auth.v1beta1.MsgUpdateParamsResponse - (*MsgNonAtomicExec)(nil), // 2: cosmos.auth.v1beta1.MsgNonAtomicExec - (*NonAtomicExecResult)(nil), // 3: cosmos.auth.v1beta1.NonAtomicExecResult - (*MsgNonAtomicExecResponse)(nil), // 4: cosmos.auth.v1beta1.MsgNonAtomicExecResponse - (*Params)(nil), // 5: cosmos.auth.v1beta1.Params - (*anypb.Any)(nil), // 6: google.protobuf.Any + (*MsgUpdateParams)(nil), // 0: cosmos.auth.v1beta1.MsgUpdateParams + (*MsgUpdateParamsResponse)(nil), // 1: cosmos.auth.v1beta1.MsgUpdateParamsResponse + (*MsgNonAtomicExec)(nil), // 2: cosmos.auth.v1beta1.MsgNonAtomicExec + (*NonAtomicExecResult)(nil), // 3: cosmos.auth.v1beta1.NonAtomicExecResult + (*MsgNonAtomicExecResponse)(nil), // 4: cosmos.auth.v1beta1.MsgNonAtomicExecResponse + (*MsgMigrateAccount)(nil), // 5: cosmos.auth.v1beta1.MsgMigrateAccount + (*MsgMigrateAccountResponse)(nil), // 6: cosmos.auth.v1beta1.MsgMigrateAccountResponse + (*Params)(nil), // 7: cosmos.auth.v1beta1.Params + (*anypb.Any)(nil), // 8: google.protobuf.Any } var file_cosmos_auth_v1beta1_tx_proto_depIdxs = []int32{ - 5, // 0: cosmos.auth.v1beta1.MsgUpdateParams.params:type_name -> cosmos.auth.v1beta1.Params - 6, // 1: cosmos.auth.v1beta1.MsgNonAtomicExec.msgs:type_name -> google.protobuf.Any - 6, // 2: cosmos.auth.v1beta1.NonAtomicExecResult.resp:type_name -> google.protobuf.Any + 7, // 0: cosmos.auth.v1beta1.MsgUpdateParams.params:type_name -> cosmos.auth.v1beta1.Params + 8, // 1: cosmos.auth.v1beta1.MsgNonAtomicExec.msgs:type_name -> google.protobuf.Any + 8, // 2: cosmos.auth.v1beta1.NonAtomicExecResult.resp:type_name -> google.protobuf.Any 3, // 3: cosmos.auth.v1beta1.MsgNonAtomicExecResponse.results:type_name -> cosmos.auth.v1beta1.NonAtomicExecResult - 0, // 4: cosmos.auth.v1beta1.Msg.UpdateParams:input_type -> cosmos.auth.v1beta1.MsgUpdateParams - 2, // 5: cosmos.auth.v1beta1.Msg.NonAtomicExec:input_type -> cosmos.auth.v1beta1.MsgNonAtomicExec - 1, // 6: cosmos.auth.v1beta1.Msg.UpdateParams:output_type -> cosmos.auth.v1beta1.MsgUpdateParamsResponse - 4, // 7: cosmos.auth.v1beta1.Msg.NonAtomicExec:output_type -> cosmos.auth.v1beta1.MsgNonAtomicExecResponse - 6, // [6:8] is the sub-list for method output_type - 4, // [4:6] is the sub-list for method input_type - 4, // [4:4] is the sub-list for extension type_name - 4, // [4:4] is the sub-list for extension extendee - 0, // [0:4] is the sub-list for field type_name + 8, // 4: cosmos.auth.v1beta1.MsgMigrateAccount.account_init_msg:type_name -> google.protobuf.Any + 8, // 5: cosmos.auth.v1beta1.MsgMigrateAccountResponse.init_response:type_name -> google.protobuf.Any + 0, // 6: cosmos.auth.v1beta1.Msg.UpdateParams:input_type -> cosmos.auth.v1beta1.MsgUpdateParams + 2, // 7: cosmos.auth.v1beta1.Msg.NonAtomicExec:input_type -> cosmos.auth.v1beta1.MsgNonAtomicExec + 5, // 8: cosmos.auth.v1beta1.Msg.MigrateAccount:input_type -> cosmos.auth.v1beta1.MsgMigrateAccount + 1, // 9: cosmos.auth.v1beta1.Msg.UpdateParams:output_type -> cosmos.auth.v1beta1.MsgUpdateParamsResponse + 4, // 10: cosmos.auth.v1beta1.Msg.NonAtomicExec:output_type -> cosmos.auth.v1beta1.MsgNonAtomicExecResponse + 6, // 11: cosmos.auth.v1beta1.Msg.MigrateAccount:output_type -> cosmos.auth.v1beta1.MsgMigrateAccountResponse + 9, // [9:12] is the sub-list for method output_type + 6, // [6:9] is the sub-list for method input_type + 6, // [6:6] is the sub-list for extension type_name + 6, // [6:6] is the sub-list for extension extendee + 0, // [0:6] is the sub-list for field type_name } func init() { file_cosmos_auth_v1beta1_tx_proto_init() } @@ -2825,6 +3947,30 @@ func file_cosmos_auth_v1beta1_tx_proto_init() { return nil } } + file_cosmos_auth_v1beta1_tx_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*MsgMigrateAccount); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cosmos_auth_v1beta1_tx_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*MsgMigrateAccountResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } } type x struct{} out := protoimpl.TypeBuilder{ @@ -2832,7 +3978,7 @@ func file_cosmos_auth_v1beta1_tx_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_cosmos_auth_v1beta1_tx_proto_rawDesc, NumEnums: 0, - NumMessages: 5, + NumMessages: 7, NumExtensions: 0, NumServices: 1, }, diff --git a/api/cosmos/auth/v1beta1/tx_grpc.pb.go b/api/cosmos/auth/v1beta1/tx_grpc.pb.go index a43c63082056..ebc4845f4431 100644 --- a/api/cosmos/auth/v1beta1/tx_grpc.pb.go +++ b/api/cosmos/auth/v1beta1/tx_grpc.pb.go @@ -19,8 +19,9 @@ import ( const _ = grpc.SupportPackageIsVersion9 const ( - Msg_UpdateParams_FullMethodName = "/cosmos.auth.v1beta1.Msg/UpdateParams" - Msg_NonAtomicExec_FullMethodName = "/cosmos.auth.v1beta1.Msg/NonAtomicExec" + Msg_UpdateParams_FullMethodName = "/cosmos.auth.v1beta1.Msg/UpdateParams" + Msg_NonAtomicExec_FullMethodName = "/cosmos.auth.v1beta1.Msg/NonAtomicExec" + Msg_MigrateAccount_FullMethodName = "/cosmos.auth.v1beta1.Msg/MigrateAccount" ) // MsgClient is the client API for Msg service. @@ -34,6 +35,8 @@ type MsgClient interface { UpdateParams(ctx context.Context, in *MsgUpdateParams, opts ...grpc.CallOption) (*MsgUpdateParamsResponse, error) // NonAtomicExec allows users to submit multiple messages for non-atomic execution. NonAtomicExec(ctx context.Context, in *MsgNonAtomicExec, opts ...grpc.CallOption) (*MsgNonAtomicExecResponse, error) + // MigrateAccount migrates the account to x/accounts. + MigrateAccount(ctx context.Context, in *MsgMigrateAccount, opts ...grpc.CallOption) (*MsgMigrateAccountResponse, error) } type msgClient struct { @@ -64,6 +67,16 @@ func (c *msgClient) NonAtomicExec(ctx context.Context, in *MsgNonAtomicExec, opt return out, nil } +func (c *msgClient) MigrateAccount(ctx context.Context, in *MsgMigrateAccount, opts ...grpc.CallOption) (*MsgMigrateAccountResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(MsgMigrateAccountResponse) + err := c.cc.Invoke(ctx, Msg_MigrateAccount_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + // MsgServer is the server API for Msg service. // All implementations must embed UnimplementedMsgServer // for forward compatibility. @@ -75,6 +88,8 @@ type MsgServer interface { UpdateParams(context.Context, *MsgUpdateParams) (*MsgUpdateParamsResponse, error) // NonAtomicExec allows users to submit multiple messages for non-atomic execution. NonAtomicExec(context.Context, *MsgNonAtomicExec) (*MsgNonAtomicExecResponse, error) + // MigrateAccount migrates the account to x/accounts. + MigrateAccount(context.Context, *MsgMigrateAccount) (*MsgMigrateAccountResponse, error) mustEmbedUnimplementedMsgServer() } @@ -91,6 +106,9 @@ func (UnimplementedMsgServer) UpdateParams(context.Context, *MsgUpdateParams) (* func (UnimplementedMsgServer) NonAtomicExec(context.Context, *MsgNonAtomicExec) (*MsgNonAtomicExecResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method NonAtomicExec not implemented") } +func (UnimplementedMsgServer) MigrateAccount(context.Context, *MsgMigrateAccount) (*MsgMigrateAccountResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method MigrateAccount not implemented") +} func (UnimplementedMsgServer) mustEmbedUnimplementedMsgServer() {} func (UnimplementedMsgServer) testEmbeddedByValue() {} @@ -148,6 +166,24 @@ func _Msg_NonAtomicExec_Handler(srv interface{}, ctx context.Context, dec func(i return interceptor(ctx, in, info, handler) } +func _Msg_MigrateAccount_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgMigrateAccount) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).MigrateAccount(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Msg_MigrateAccount_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).MigrateAccount(ctx, req.(*MsgMigrateAccount)) + } + return interceptor(ctx, in, info, handler) +} + // Msg_ServiceDesc is the grpc.ServiceDesc for Msg service. // It's only intended for direct use with grpc.RegisterService, // and not to be introspected or modified (even as a copy) @@ -163,6 +199,10 @@ var Msg_ServiceDesc = grpc.ServiceDesc{ MethodName: "NonAtomicExec", Handler: _Msg_NonAtomicExec_Handler, }, + { + MethodName: "MigrateAccount", + Handler: _Msg_MigrateAccount_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "cosmos/auth/v1beta1/tx.proto", diff --git a/api/cosmos/staking/v1beta1/query.pulsar.go b/api/cosmos/staking/v1beta1/query.pulsar.go index 2f727386e423..84155febc716 100644 --- a/api/cosmos/staking/v1beta1/query.pulsar.go +++ b/api/cosmos/staking/v1beta1/query.pulsar.go @@ -15713,299 +15713,300 @@ var file_cosmos_staking_v1beta1_query_proto_rawDesc = []byte{ 0x0b, 0x32, 0x27, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x50, 0x61, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x0a, 0x70, 0x61, 0x67, 0x69, - 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xbe, 0x02, 0x0a, 0x19, 0x51, 0x75, 0x65, 0x72, 0x79, + 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xd0, 0x02, 0x0a, 0x19, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x65, 0x64, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3f, 0x0a, 0x0e, 0x64, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xd2, 0xb4, 0x2d, 0x14, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x0d, 0x64, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x6f, - 0x72, 0x41, 0x64, 0x64, 0x72, 0x12, 0x46, 0x0a, 0x12, 0x73, 0x72, 0x63, 0x5f, 0x76, 0x61, 0x6c, + 0x72, 0x41, 0x64, 0x64, 0x72, 0x12, 0x4f, 0x0a, 0x12, 0x73, 0x72, 0x63, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x09, 0x42, 0x18, 0xd2, 0xb4, 0x2d, 0x14, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x64, - 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x10, 0x73, 0x72, 0x63, - 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x41, 0x64, 0x64, 0x72, 0x12, 0x46, 0x0a, - 0x12, 0x64, 0x73, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x61, - 0x64, 0x64, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xd2, 0xb4, 0x2d, 0x14, 0x63, - 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, - 0x69, 0x6e, 0x67, 0x52, 0x10, 0x64, 0x73, 0x74, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, - 0x72, 0x41, 0x64, 0x64, 0x72, 0x12, 0x46, 0x0a, 0x0a, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x63, 0x6f, 0x73, 0x6d, - 0x6f, 0x73, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x76, 0x31, - 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x50, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x52, 0x0a, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x08, 0x88, - 0xa0, 0x1f, 0x00, 0xe8, 0xa0, 0x1f, 0x00, 0x22, 0xd5, 0x01, 0x0a, 0x1a, 0x51, 0x75, 0x65, 0x72, - 0x79, 0x52, 0x65, 0x64, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6e, 0x0a, 0x16, 0x72, 0x65, 0x64, 0x65, 0x6c, 0x65, - 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, - 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, - 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, - 0x52, 0x65, 0x64, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x09, 0xc8, 0xde, 0x1f, 0x00, 0xa8, 0xe7, 0xb0, 0x2a, 0x01, 0x52, - 0x15, 0x72, 0x65, 0x64, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x12, 0x47, 0x0a, 0x0a, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x63, 0x6f, 0x73, - 0x6d, 0x6f, 0x73, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x76, - 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x50, 0x61, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x52, 0x0a, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, - 0xb4, 0x01, 0x0a, 0x1f, 0x51, 0x75, 0x65, 0x72, 0x79, 0x44, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, - 0x6f, 0x72, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x12, 0x3f, 0x0a, 0x0e, 0x64, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, - 0x5f, 0x61, 0x64, 0x64, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xd2, 0xb4, 0x2d, - 0x14, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, - 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x0d, 0x64, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, - 0x41, 0x64, 0x64, 0x72, 0x12, 0x46, 0x0a, 0x0a, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, - 0x73, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x62, - 0x65, 0x74, 0x61, 0x31, 0x2e, 0x50, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x52, 0x0a, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x08, 0x88, 0xa0, - 0x1f, 0x00, 0xe8, 0xa0, 0x1f, 0x00, 0x22, 0xb9, 0x01, 0x0a, 0x20, 0x51, 0x75, 0x65, 0x72, 0x79, - 0x44, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, - 0x6f, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4c, 0x0a, 0x0a, 0x76, - 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x21, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, - 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, - 0x6f, 0x72, 0x42, 0x09, 0xc8, 0xde, 0x1f, 0x00, 0xa8, 0xe7, 0xb0, 0x2a, 0x01, 0x52, 0x0a, 0x76, - 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x12, 0x47, 0x0a, 0x0a, 0x70, 0x61, 0x67, - 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, - 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x2e, 0x71, 0x75, 0x65, 0x72, - 0x79, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x50, 0x61, 0x67, 0x65, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x0a, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x22, 0xb5, 0x01, 0x0a, 0x1e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x44, 0x65, 0x6c, 0x65, - 0x67, 0x61, 0x74, 0x6f, 0x72, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, + 0x09, 0x42, 0x21, 0xd2, 0xb4, 0x2d, 0x1d, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x56, 0x61, + 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, + 0x72, 0x69, 0x6e, 0x67, 0x52, 0x10, 0x73, 0x72, 0x63, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, + 0x6f, 0x72, 0x41, 0x64, 0x64, 0x72, 0x12, 0x4f, 0x0a, 0x12, 0x64, 0x73, 0x74, 0x5f, 0x76, 0x61, + 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x09, 0x42, 0x21, 0xd2, 0xb4, 0x2d, 0x1d, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x56, + 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, + 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x10, 0x64, 0x73, 0x74, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, + 0x74, 0x6f, 0x72, 0x41, 0x64, 0x64, 0x72, 0x12, 0x46, 0x0a, 0x0a, 0x70, 0x61, 0x67, 0x69, 0x6e, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x63, 0x6f, + 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, + 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x50, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x52, 0x0a, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3a, + 0x08, 0x88, 0xa0, 0x1f, 0x00, 0xe8, 0xa0, 0x1f, 0x00, 0x22, 0xd5, 0x01, 0x0a, 0x1a, 0x51, 0x75, + 0x65, 0x72, 0x79, 0x52, 0x65, 0x64, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6e, 0x0a, 0x16, 0x72, 0x65, 0x64, 0x65, + 0x6c, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, + 0x73, 0x2e, 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, + 0x31, 0x2e, 0x52, 0x65, 0x64, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x09, 0xc8, 0xde, 0x1f, 0x00, 0xa8, 0xe7, 0xb0, 0x2a, + 0x01, 0x52, 0x15, 0x72, 0x65, 0x64, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x12, 0x47, 0x0a, 0x0a, 0x70, 0x61, 0x67, 0x69, + 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x63, + 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, + 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x50, 0x61, 0x67, 0x65, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x0a, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x22, 0xb4, 0x01, 0x0a, 0x1f, 0x51, 0x75, 0x65, 0x72, 0x79, 0x44, 0x65, 0x6c, 0x65, 0x67, + 0x61, 0x74, 0x6f, 0x72, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3f, 0x0a, 0x0e, 0x64, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xd2, 0xb4, 0x2d, 0x14, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x0d, 0x64, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, - 0x6f, 0x72, 0x41, 0x64, 0x64, 0x72, 0x12, 0x48, 0x0a, 0x0e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, - 0x74, 0x6f, 0x72, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x21, - 0xd2, 0xb4, 0x2d, 0x1d, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, - 0x61, 0x74, 0x6f, 0x72, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, - 0x67, 0x52, 0x0d, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x41, 0x64, 0x64, 0x72, - 0x3a, 0x08, 0x88, 0xa0, 0x1f, 0x00, 0xe8, 0xa0, 0x1f, 0x00, 0x22, 0x6d, 0x0a, 0x1f, 0x51, 0x75, - 0x65, 0x72, 0x79, 0x44, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, 0x56, 0x61, 0x6c, 0x69, - 0x64, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4a, 0x0a, - 0x09, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x21, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, - 0x67, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, - 0x74, 0x6f, 0x72, 0x42, 0x09, 0xc8, 0xde, 0x1f, 0x00, 0xa8, 0xe7, 0xb0, 0x2a, 0x01, 0x52, 0x09, - 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x22, 0x38, 0x0a, 0x1a, 0x51, 0x75, 0x65, - 0x72, 0x79, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x69, 0x63, 0x61, 0x6c, 0x49, 0x6e, 0x66, 0x6f, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, - 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3a, - 0x02, 0x18, 0x01, 0x22, 0x61, 0x0a, 0x1b, 0x51, 0x75, 0x65, 0x72, 0x79, 0x48, 0x69, 0x73, 0x74, - 0x6f, 0x72, 0x69, 0x63, 0x61, 0x6c, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x3e, 0x0a, 0x04, 0x68, 0x69, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x26, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, - 0x67, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, - 0x69, 0x63, 0x61, 0x6c, 0x49, 0x6e, 0x66, 0x6f, 0x42, 0x02, 0x18, 0x01, 0x52, 0x04, 0x68, 0x69, - 0x73, 0x74, 0x3a, 0x02, 0x18, 0x01, 0x22, 0x12, 0x0a, 0x10, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, - 0x6f, 0x6f, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x50, 0x0a, 0x11, 0x51, 0x75, - 0x65, 0x72, 0x79, 0x50, 0x6f, 0x6f, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x3b, 0x0a, 0x04, 0x70, 0x6f, 0x6f, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, - 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x76, - 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x50, 0x6f, 0x6f, 0x6c, 0x42, 0x09, 0xc8, 0xde, 0x1f, - 0x00, 0xa8, 0xe7, 0xb0, 0x2a, 0x01, 0x52, 0x04, 0x70, 0x6f, 0x6f, 0x6c, 0x22, 0x14, 0x0a, 0x12, - 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x22, 0x58, 0x0a, 0x13, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, - 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x41, 0x0a, 0x06, 0x70, 0x61, 0x72, - 0x61, 0x6d, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x63, 0x6f, 0x73, 0x6d, - 0x6f, 0x73, 0x2e, 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, - 0x61, 0x31, 0x2e, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x42, 0x09, 0xc8, 0xde, 0x1f, 0x00, 0xa8, - 0xe7, 0xb0, 0x2a, 0x01, 0x52, 0x06, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x32, 0xb3, 0x16, 0x0a, - 0x05, 0x51, 0x75, 0x65, 0x72, 0x79, 0x12, 0x9e, 0x01, 0x0a, 0x0a, 0x56, 0x61, 0x6c, 0x69, 0x64, - 0x61, 0x74, 0x6f, 0x72, 0x73, 0x12, 0x2e, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x73, - 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x51, - 0x75, 0x65, 0x72, 0x79, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2f, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x73, - 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x51, - 0x75, 0x65, 0x72, 0x79, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2f, 0x88, 0xe7, 0xb0, 0x2a, 0x01, 0x82, 0xd3, 0xe4, - 0x93, 0x02, 0x24, 0x12, 0x22, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x73, 0x74, 0x61, + 0x6f, 0x72, 0x41, 0x64, 0x64, 0x72, 0x12, 0x46, 0x0a, 0x0a, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x63, 0x6f, 0x73, + 0x6d, 0x6f, 0x73, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x76, + 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x50, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x52, 0x0a, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x08, + 0x88, 0xa0, 0x1f, 0x00, 0xe8, 0xa0, 0x1f, 0x00, 0x22, 0xb9, 0x01, 0x0a, 0x20, 0x51, 0x75, 0x65, + 0x72, 0x79, 0x44, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, 0x56, 0x61, 0x6c, 0x69, 0x64, + 0x61, 0x74, 0x6f, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4c, 0x0a, + 0x0a, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x21, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x73, 0x74, 0x61, 0x6b, 0x69, + 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, + 0x61, 0x74, 0x6f, 0x72, 0x42, 0x09, 0xc8, 0xde, 0x1f, 0x00, 0xa8, 0xe7, 0xb0, 0x2a, 0x01, 0x52, + 0x0a, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x12, 0x47, 0x0a, 0x0a, 0x70, + 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x27, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x2e, 0x71, 0x75, + 0x65, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x50, 0x61, 0x67, 0x65, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x0a, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xb5, 0x01, 0x0a, 0x1e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x44, 0x65, + 0x6c, 0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3f, 0x0a, 0x0e, 0x64, 0x65, 0x6c, 0x65, 0x67, + 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, + 0x18, 0xd2, 0xb4, 0x2d, 0x14, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, + 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x0d, 0x64, 0x65, 0x6c, 0x65, 0x67, + 0x61, 0x74, 0x6f, 0x72, 0x41, 0x64, 0x64, 0x72, 0x12, 0x48, 0x0a, 0x0e, 0x76, 0x61, 0x6c, 0x69, + 0x64, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x42, 0x21, 0xd2, 0xb4, 0x2d, 0x1d, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x56, 0x61, 0x6c, + 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, + 0x69, 0x6e, 0x67, 0x52, 0x0d, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x41, 0x64, + 0x64, 0x72, 0x3a, 0x08, 0x88, 0xa0, 0x1f, 0x00, 0xe8, 0xa0, 0x1f, 0x00, 0x22, 0x6d, 0x0a, 0x1f, + 0x51, 0x75, 0x65, 0x72, 0x79, 0x44, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, 0x56, 0x61, + 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x4a, 0x0a, 0x09, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x73, 0x74, 0x61, 0x6b, + 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x56, 0x61, 0x6c, 0x69, + 0x64, 0x61, 0x74, 0x6f, 0x72, 0x42, 0x09, 0xc8, 0xde, 0x1f, 0x00, 0xa8, 0xe7, 0xb0, 0x2a, 0x01, + 0x52, 0x09, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x22, 0x38, 0x0a, 0x1a, 0x51, + 0x75, 0x65, 0x72, 0x79, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x69, 0x63, 0x61, 0x6c, 0x49, 0x6e, + 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x68, 0x65, 0x69, + 0x67, 0x68, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, + 0x74, 0x3a, 0x02, 0x18, 0x01, 0x22, 0x61, 0x0a, 0x1b, 0x51, 0x75, 0x65, 0x72, 0x79, 0x48, 0x69, + 0x73, 0x74, 0x6f, 0x72, 0x69, 0x63, 0x61, 0x6c, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3e, 0x0a, 0x04, 0x68, 0x69, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x73, 0x74, 0x61, 0x6b, + 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x48, 0x69, 0x73, 0x74, + 0x6f, 0x72, 0x69, 0x63, 0x61, 0x6c, 0x49, 0x6e, 0x66, 0x6f, 0x42, 0x02, 0x18, 0x01, 0x52, 0x04, + 0x68, 0x69, 0x73, 0x74, 0x3a, 0x02, 0x18, 0x01, 0x22, 0x12, 0x0a, 0x10, 0x51, 0x75, 0x65, 0x72, + 0x79, 0x50, 0x6f, 0x6f, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x50, 0x0a, 0x11, + 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x6f, 0x6f, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x3b, 0x0a, 0x04, 0x70, 0x6f, 0x6f, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x1c, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, + 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x50, 0x6f, 0x6f, 0x6c, 0x42, 0x09, 0xc8, + 0xde, 0x1f, 0x00, 0xa8, 0xe7, 0xb0, 0x2a, 0x01, 0x52, 0x04, 0x70, 0x6f, 0x6f, 0x6c, 0x22, 0x14, + 0x0a, 0x12, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x22, 0x58, 0x0a, 0x13, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x61, 0x72, + 0x61, 0x6d, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x41, 0x0a, 0x06, 0x70, + 0x61, 0x72, 0x61, 0x6d, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x63, 0x6f, + 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x62, + 0x65, 0x74, 0x61, 0x31, 0x2e, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x42, 0x09, 0xc8, 0xde, 0x1f, + 0x00, 0xa8, 0xe7, 0xb0, 0x2a, 0x01, 0x52, 0x06, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x32, 0xb3, + 0x16, 0x0a, 0x05, 0x51, 0x75, 0x65, 0x72, 0x79, 0x12, 0x9e, 0x01, 0x0a, 0x0a, 0x56, 0x61, 0x6c, + 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x12, 0x2e, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, + 0x2e, 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, + 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2f, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, + 0x2e, 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, + 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2f, 0x88, 0xe7, 0xb0, 0x2a, 0x01, 0x82, + 0xd3, 0xe4, 0x93, 0x02, 0x24, 0x12, 0x22, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x73, + 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x76, + 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x12, 0xac, 0x01, 0x0a, 0x09, 0x56, 0x61, + 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x12, 0x2d, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, + 0x2e, 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, + 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, + 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, + 0x51, 0x75, 0x65, 0x72, 0x79, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x40, 0x88, 0xe7, 0xb0, 0x2a, 0x01, 0x82, 0xd3, 0xe4, + 0x93, 0x02, 0x35, 0x12, 0x33, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, - 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x12, 0xac, 0x01, 0x0a, 0x09, 0x56, 0x61, 0x6c, 0x69, - 0x64, 0x61, 0x74, 0x6f, 0x72, 0x12, 0x2d, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x73, - 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x51, - 0x75, 0x65, 0x72, 0x79, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x73, 0x74, - 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x51, 0x75, - 0x65, 0x72, 0x79, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x40, 0x88, 0xe7, 0xb0, 0x2a, 0x01, 0x82, 0xd3, 0xe4, 0x93, 0x02, - 0x35, 0x12, 0x33, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x73, 0x74, 0x61, 0x6b, 0x69, - 0x6e, 0x67, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, - 0x61, 0x74, 0x6f, 0x72, 0x73, 0x2f, 0x7b, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, - 0x5f, 0x61, 0x64, 0x64, 0x72, 0x7d, 0x12, 0xd9, 0x01, 0x0a, 0x14, 0x56, 0x61, 0x6c, 0x69, 0x64, - 0x61, 0x74, 0x6f, 0x72, 0x44, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, - 0x38, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, - 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x56, 0x61, - 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x44, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x39, 0x2e, 0x63, 0x6f, 0x73, 0x6d, + 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x2f, 0x7b, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, + 0x6f, 0x72, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x7d, 0x12, 0xd9, 0x01, 0x0a, 0x14, 0x56, 0x61, 0x6c, + 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x44, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x12, 0x38, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x73, 0x74, 0x61, 0x6b, 0x69, + 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, + 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x44, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x39, 0x2e, 0x63, 0x6f, + 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x62, + 0x65, 0x74, 0x61, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, + 0x74, 0x6f, 0x72, 0x44, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x4c, 0x88, 0xe7, 0xb0, 0x2a, 0x01, 0x82, 0xd3, 0xe4, + 0x93, 0x02, 0x41, 0x12, 0x3f, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x73, 0x74, 0x61, + 0x6b, 0x69, 0x6e, 0x67, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, + 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x2f, 0x7b, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, + 0x6f, 0x72, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x7d, 0x2f, 0x64, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x12, 0xfe, 0x01, 0x0a, 0x1d, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, + 0x6f, 0x72, 0x55, 0x6e, 0x62, 0x6f, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x44, 0x65, 0x6c, 0x65, 0x67, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x41, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, + 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, + 0x51, 0x75, 0x65, 0x72, 0x79, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x55, 0x6e, + 0x62, 0x6f, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x44, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x42, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, - 0x72, 0x44, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x4c, 0x88, 0xe7, 0xb0, 0x2a, 0x01, 0x82, 0xd3, 0xe4, 0x93, 0x02, - 0x41, 0x12, 0x3f, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x73, 0x74, 0x61, 0x6b, 0x69, - 0x6e, 0x67, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, - 0x61, 0x74, 0x6f, 0x72, 0x73, 0x2f, 0x7b, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, - 0x5f, 0x61, 0x64, 0x64, 0x72, 0x7d, 0x2f, 0x64, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x73, 0x12, 0xfe, 0x01, 0x0a, 0x1d, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, - 0x55, 0x6e, 0x62, 0x6f, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x44, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x41, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x73, 0x74, - 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x51, 0x75, - 0x65, 0x72, 0x79, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x55, 0x6e, 0x62, 0x6f, - 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x44, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x42, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, - 0x2e, 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x55, - 0x6e, 0x62, 0x6f, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x44, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x56, 0x88, 0xe7, 0xb0, - 0x2a, 0x01, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x4b, 0x12, 0x49, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, - 0x73, 0x2f, 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, - 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x2f, 0x7b, 0x76, 0x61, - 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x7d, 0x2f, 0x75, 0x6e, - 0x62, 0x6f, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x64, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x12, 0xcc, 0x01, 0x0a, 0x0a, 0x44, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x12, 0x2e, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x73, 0x74, 0x61, 0x6b, - 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, - 0x79, 0x44, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x2f, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x73, 0x74, 0x61, 0x6b, - 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, - 0x79, 0x44, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x5d, 0x88, 0xe7, 0xb0, 0x2a, 0x01, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x52, - 0x12, 0x50, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, - 0x67, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, - 0x74, 0x6f, 0x72, 0x73, 0x2f, 0x7b, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x5f, - 0x61, 0x64, 0x64, 0x72, 0x7d, 0x2f, 0x64, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x73, 0x2f, 0x7b, 0x64, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x61, 0x64, 0x64, - 0x72, 0x7d, 0x12, 0xfc, 0x01, 0x0a, 0x13, 0x55, 0x6e, 0x62, 0x6f, 0x6e, 0x64, 0x69, 0x6e, 0x67, - 0x44, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x37, 0x2e, 0x63, 0x6f, 0x73, - 0x6d, 0x6f, 0x73, 0x2e, 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x62, 0x65, - 0x74, 0x61, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x55, 0x6e, 0x62, 0x6f, 0x6e, 0x64, 0x69, - 0x6e, 0x67, 0x44, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x38, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x73, 0x74, 0x61, - 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x51, 0x75, 0x65, - 0x72, 0x79, 0x55, 0x6e, 0x62, 0x6f, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x44, 0x65, 0x6c, 0x65, 0x67, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x72, 0x88, - 0xe7, 0xb0, 0x2a, 0x01, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x67, 0x12, 0x65, 0x2f, 0x63, 0x6f, 0x73, + 0x72, 0x55, 0x6e, 0x62, 0x6f, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x44, 0x65, 0x6c, 0x65, 0x67, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x56, 0x88, + 0xe7, 0xb0, 0x2a, 0x01, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x4b, 0x12, 0x49, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x2f, 0x7b, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x7d, 0x2f, - 0x64, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x7b, 0x64, 0x65, 0x6c, - 0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x7d, 0x2f, 0x75, 0x6e, 0x62, - 0x6f, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x64, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x12, 0xce, 0x01, 0x0a, 0x14, 0x44, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, 0x44, - 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x38, 0x2e, 0x63, 0x6f, 0x73, - 0x6d, 0x6f, 0x73, 0x2e, 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x62, 0x65, - 0x74, 0x61, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x44, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, - 0x6f, 0x72, 0x44, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x39, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x73, 0x74, + 0x75, 0x6e, 0x62, 0x6f, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x64, 0x65, 0x6c, 0x65, 0x67, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0xcc, 0x01, 0x0a, 0x0a, 0x44, 0x65, 0x6c, 0x65, 0x67, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2e, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x51, 0x75, - 0x65, 0x72, 0x79, 0x44, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, 0x44, 0x65, 0x6c, 0x65, - 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x41, 0x88, 0xe7, 0xb0, 0x2a, 0x01, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x36, 0x12, 0x34, 0x2f, 0x63, - 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2f, 0x76, 0x31, - 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x64, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x73, 0x2f, 0x7b, 0x64, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x61, 0x64, 0x64, - 0x72, 0x7d, 0x12, 0xfe, 0x01, 0x0a, 0x1d, 0x44, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, - 0x55, 0x6e, 0x62, 0x6f, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x44, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x41, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x73, 0x74, + 0x65, 0x72, 0x79, 0x44, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2f, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x51, 0x75, - 0x65, 0x72, 0x79, 0x44, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, 0x55, 0x6e, 0x62, 0x6f, - 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x44, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x42, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, - 0x2e, 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x44, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, 0x55, - 0x6e, 0x62, 0x6f, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x44, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x56, 0x88, 0xe7, 0xb0, - 0x2a, 0x01, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x4b, 0x12, 0x49, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, - 0x73, 0x2f, 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, - 0x31, 0x2f, 0x64, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x2f, 0x7b, 0x64, 0x65, - 0x6c, 0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x7d, 0x2f, 0x75, 0x6e, - 0x62, 0x6f, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x64, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x12, 0xc6, 0x01, 0x0a, 0x0d, 0x52, 0x65, 0x64, 0x65, 0x6c, 0x65, 0x67, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x31, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x73, + 0x65, 0x72, 0x79, 0x44, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x5d, 0x88, 0xe7, 0xb0, 0x2a, 0x01, 0x82, 0xd3, 0xe4, 0x93, + 0x02, 0x52, 0x12, 0x50, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x73, 0x74, 0x61, 0x6b, + 0x69, 0x6e, 0x67, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, + 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x2f, 0x7b, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, + 0x72, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x7d, 0x2f, 0x64, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x2f, 0x7b, 0x64, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x61, + 0x64, 0x64, 0x72, 0x7d, 0x12, 0xfc, 0x01, 0x0a, 0x13, 0x55, 0x6e, 0x62, 0x6f, 0x6e, 0x64, 0x69, + 0x6e, 0x67, 0x44, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x37, 0x2e, 0x63, + 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x31, + 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x55, 0x6e, 0x62, 0x6f, 0x6e, + 0x64, 0x69, 0x6e, 0x67, 0x44, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x38, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x51, - 0x75, 0x65, 0x72, 0x79, 0x52, 0x65, 0x64, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x32, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, - 0x73, 0x2e, 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, - 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x65, 0x64, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x4e, 0x88, 0xe7, - 0xb0, 0x2a, 0x01, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x43, 0x12, 0x41, 0x2f, 0x63, 0x6f, 0x73, 0x6d, - 0x6f, 0x73, 0x2f, 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, - 0x61, 0x31, 0x2f, 0x64, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x2f, 0x7b, 0x64, - 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x7d, 0x2f, 0x72, - 0x65, 0x64, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0xd5, 0x01, 0x0a, - 0x13, 0x44, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, - 0x74, 0x6f, 0x72, 0x73, 0x12, 0x37, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x73, 0x74, - 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x51, 0x75, - 0x65, 0x72, 0x79, 0x44, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, 0x56, 0x61, 0x6c, 0x69, - 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x38, 0x2e, + 0x75, 0x65, 0x72, 0x79, 0x55, 0x6e, 0x62, 0x6f, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x44, 0x65, 0x6c, + 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, + 0x72, 0x88, 0xe7, 0xb0, 0x2a, 0x01, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x67, 0x12, 0x65, 0x2f, 0x63, + 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2f, 0x76, 0x31, + 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, + 0x2f, 0x7b, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x61, 0x64, 0x64, 0x72, + 0x7d, 0x2f, 0x64, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x7b, 0x64, + 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x7d, 0x2f, 0x75, + 0x6e, 0x62, 0x6f, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x64, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x12, 0xce, 0x01, 0x0a, 0x14, 0x44, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x6f, + 0x72, 0x44, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x38, 0x2e, 0x63, + 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x31, + 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x44, 0x65, 0x6c, 0x65, 0x67, + 0x61, 0x74, 0x6f, 0x72, 0x44, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x39, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, + 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, + 0x51, 0x75, 0x65, 0x72, 0x79, 0x44, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, 0x44, 0x65, + 0x6c, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x41, 0x88, 0xe7, 0xb0, 0x2a, 0x01, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x36, 0x12, 0x34, + 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2f, + 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x64, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x2f, 0x7b, 0x64, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x61, + 0x64, 0x64, 0x72, 0x7d, 0x12, 0xfe, 0x01, 0x0a, 0x1d, 0x44, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, + 0x6f, 0x72, 0x55, 0x6e, 0x62, 0x6f, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x44, 0x65, 0x6c, 0x65, 0x67, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x41, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, + 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, + 0x51, 0x75, 0x65, 0x72, 0x79, 0x44, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, 0x55, 0x6e, + 0x62, 0x6f, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x44, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x42, 0x2e, 0x63, 0x6f, 0x73, 0x6d, + 0x6f, 0x73, 0x2e, 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, + 0x61, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x44, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x6f, + 0x72, 0x55, 0x6e, 0x62, 0x6f, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x44, 0x65, 0x6c, 0x65, 0x67, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x56, 0x88, + 0xe7, 0xb0, 0x2a, 0x01, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x4b, 0x12, 0x49, 0x2f, 0x63, 0x6f, 0x73, + 0x6d, 0x6f, 0x73, 0x2f, 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2f, 0x76, 0x31, 0x62, 0x65, + 0x74, 0x61, 0x31, 0x2f, 0x64, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x2f, 0x7b, + 0x64, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x7d, 0x2f, + 0x75, 0x6e, 0x62, 0x6f, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x64, 0x65, 0x6c, 0x65, 0x67, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0xc6, 0x01, 0x0a, 0x0d, 0x52, 0x65, 0x64, 0x65, 0x6c, 0x65, + 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x31, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, + 0x2e, 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, + 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x65, 0x64, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x32, 0x2e, 0x63, 0x6f, 0x73, + 0x6d, 0x6f, 0x73, 0x2e, 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x62, 0x65, + 0x74, 0x61, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x65, 0x64, 0x65, 0x6c, 0x65, 0x67, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x4e, + 0x88, 0xe7, 0xb0, 0x2a, 0x01, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x43, 0x12, 0x41, 0x2f, 0x63, 0x6f, + 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2f, 0x76, 0x31, 0x62, + 0x65, 0x74, 0x61, 0x31, 0x2f, 0x64, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x2f, + 0x7b, 0x64, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x7d, + 0x2f, 0x72, 0x65, 0x64, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0xd5, + 0x01, 0x0a, 0x13, 0x44, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, 0x56, 0x61, 0x6c, 0x69, + 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x12, 0x37, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, + 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, + 0x51, 0x75, 0x65, 0x72, 0x79, 0x44, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, 0x56, 0x61, + 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x38, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, + 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x44, 0x65, + 0x6c, 0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, + 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x4b, 0x88, 0xe7, 0xb0, 0x2a, 0x01, + 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x40, 0x12, 0x3e, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, + 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, + 0x64, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x2f, 0x7b, 0x64, 0x65, 0x6c, 0x65, + 0x67, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x7d, 0x2f, 0x76, 0x61, 0x6c, 0x69, + 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x12, 0xe3, 0x01, 0x0a, 0x12, 0x44, 0x65, 0x6c, 0x65, 0x67, + 0x61, 0x74, 0x6f, 0x72, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x12, 0x36, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x44, 0x65, 0x6c, 0x65, - 0x67, 0x61, 0x74, 0x6f, 0x72, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x4b, 0x88, 0xe7, 0xb0, 0x2a, 0x01, 0x82, 0xd3, - 0xe4, 0x93, 0x02, 0x40, 0x12, 0x3e, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x73, 0x74, - 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x64, 0x65, - 0x6c, 0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x2f, 0x7b, 0x64, 0x65, 0x6c, 0x65, 0x67, 0x61, - 0x74, 0x6f, 0x72, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x7d, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, - 0x74, 0x6f, 0x72, 0x73, 0x12, 0xe3, 0x01, 0x0a, 0x12, 0x44, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, - 0x6f, 0x72, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x12, 0x36, 0x2e, 0x63, 0x6f, - 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x62, - 0x65, 0x74, 0x61, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x44, 0x65, 0x6c, 0x65, 0x67, 0x61, - 0x74, 0x6f, 0x72, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x37, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x73, 0x74, 0x61, + 0x67, 0x61, 0x74, 0x6f, 0x72, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x37, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x73, + 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x51, + 0x75, 0x65, 0x72, 0x79, 0x44, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, 0x56, 0x61, 0x6c, + 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x5c, + 0x88, 0xe7, 0xb0, 0x2a, 0x01, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x51, 0x12, 0x4f, 0x2f, 0x63, 0x6f, + 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2f, 0x76, 0x31, 0x62, + 0x65, 0x74, 0x61, 0x31, 0x2f, 0x64, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x2f, + 0x7b, 0x64, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x7d, + 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x2f, 0x7b, 0x76, 0x61, 0x6c, + 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x7d, 0x12, 0xbb, 0x01, 0x0a, + 0x0e, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x69, 0x63, 0x61, 0x6c, 0x49, 0x6e, 0x66, 0x6f, 0x12, + 0x32, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, + 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x48, 0x69, + 0x73, 0x74, 0x6f, 0x72, 0x69, 0x63, 0x61, 0x6c, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x33, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x51, 0x75, 0x65, - 0x72, 0x79, 0x44, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, 0x56, 0x61, 0x6c, 0x69, 0x64, - 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x5c, 0x88, 0xe7, - 0xb0, 0x2a, 0x01, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x51, 0x12, 0x4f, 0x2f, 0x63, 0x6f, 0x73, 0x6d, - 0x6f, 0x73, 0x2f, 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, - 0x61, 0x31, 0x2f, 0x64, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x2f, 0x7b, 0x64, - 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x7d, 0x2f, 0x76, - 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x2f, 0x7b, 0x76, 0x61, 0x6c, 0x69, 0x64, - 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x7d, 0x12, 0xbb, 0x01, 0x0a, 0x0e, 0x48, - 0x69, 0x73, 0x74, 0x6f, 0x72, 0x69, 0x63, 0x61, 0x6c, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x32, 0x2e, + 0x72, 0x79, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x69, 0x63, 0x61, 0x6c, 0x49, 0x6e, 0x66, 0x6f, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x40, 0x88, 0xe7, 0xb0, 0x2a, 0x01, 0x82, + 0xd3, 0xe4, 0x93, 0x02, 0x32, 0x12, 0x30, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x73, + 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x68, + 0x69, 0x73, 0x74, 0x6f, 0x72, 0x69, 0x63, 0x61, 0x6c, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x2f, 0x7b, + 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x7d, 0x88, 0x02, 0x01, 0x12, 0x86, 0x01, 0x0a, 0x04, 0x50, + 0x6f, 0x6f, 0x6c, 0x12, 0x28, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x73, 0x74, 0x61, + 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x51, 0x75, 0x65, + 0x72, 0x79, 0x50, 0x6f, 0x6f, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x76, - 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x48, 0x69, 0x73, 0x74, - 0x6f, 0x72, 0x69, 0x63, 0x61, 0x6c, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x33, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x73, 0x74, 0x61, 0x6b, 0x69, - 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, - 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x69, 0x63, 0x61, 0x6c, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x40, 0x88, 0xe7, 0xb0, 0x2a, 0x01, 0x82, 0xd3, 0xe4, - 0x93, 0x02, 0x32, 0x12, 0x30, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x73, 0x74, 0x61, - 0x6b, 0x69, 0x6e, 0x67, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x68, 0x69, 0x73, - 0x74, 0x6f, 0x72, 0x69, 0x63, 0x61, 0x6c, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x2f, 0x7b, 0x68, 0x65, - 0x69, 0x67, 0x68, 0x74, 0x7d, 0x88, 0x02, 0x01, 0x12, 0x86, 0x01, 0x0a, 0x04, 0x50, 0x6f, 0x6f, - 0x6c, 0x12, 0x28, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x73, 0x74, 0x61, 0x6b, 0x69, - 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, - 0x50, 0x6f, 0x6f, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x63, 0x6f, - 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x62, - 0x65, 0x74, 0x61, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x6f, 0x6f, 0x6c, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x29, 0x88, 0xe7, 0xb0, 0x2a, 0x01, 0x82, 0xd3, 0xe4, - 0x93, 0x02, 0x1e, 0x12, 0x1c, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x73, 0x74, 0x61, - 0x6b, 0x69, 0x6e, 0x67, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x70, 0x6f, 0x6f, - 0x6c, 0x12, 0x8e, 0x01, 0x0a, 0x06, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x2a, 0x2e, 0x63, - 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x31, - 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, - 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, - 0x73, 0x2e, 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, - 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2b, 0x88, 0xe7, 0xb0, 0x2a, 0x01, 0x82, 0xd3, 0xe4, 0x93, - 0x02, 0x20, 0x12, 0x1e, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x73, 0x74, 0x61, 0x6b, - 0x69, 0x6e, 0x67, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x70, 0x61, 0x72, 0x61, - 0x6d, 0x73, 0x42, 0xda, 0x01, 0x0a, 0x1a, 0x63, 0x6f, 0x6d, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, - 0x73, 0x2e, 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, - 0x31, 0x42, 0x0a, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, - 0x36, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x73, 0x64, 0x6b, 0x2e, 0x69, 0x6f, 0x2f, 0x61, 0x70, - 0x69, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, - 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x3b, 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, - 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0xa2, 0x02, 0x03, 0x43, 0x53, 0x58, 0xaa, 0x02, 0x16, - 0x43, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x53, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x56, - 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0xca, 0x02, 0x16, 0x43, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x5c, - 0x53, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x5c, 0x56, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0xe2, - 0x02, 0x22, 0x43, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x5c, 0x53, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, - 0x5c, 0x56, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, - 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x18, 0x43, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x3a, 0x3a, 0x53, - 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x62, - 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x6f, 0x6f, 0x6c, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x29, 0x88, 0xe7, 0xb0, 0x2a, 0x01, 0x82, + 0xd3, 0xe4, 0x93, 0x02, 0x1e, 0x12, 0x1c, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x73, + 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x70, + 0x6f, 0x6f, 0x6c, 0x12, 0x8e, 0x01, 0x0a, 0x06, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x2a, + 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2e, + 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x61, 0x72, + 0x61, 0x6d, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x63, 0x6f, 0x73, + 0x6d, 0x6f, 0x73, 0x2e, 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x62, 0x65, + 0x74, 0x61, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2b, 0x88, 0xe7, 0xb0, 0x2a, 0x01, 0x82, 0xd3, + 0xe4, 0x93, 0x02, 0x20, 0x12, 0x1e, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x73, 0x74, + 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x70, 0x61, + 0x72, 0x61, 0x6d, 0x73, 0x42, 0xda, 0x01, 0x0a, 0x1a, 0x63, 0x6f, 0x6d, 0x2e, 0x63, 0x6f, 0x73, + 0x6d, 0x6f, 0x73, 0x2e, 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x62, 0x65, + 0x74, 0x61, 0x31, 0x42, 0x0a, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, + 0x01, 0x5a, 0x36, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x73, 0x64, 0x6b, 0x2e, 0x69, 0x6f, 0x2f, + 0x61, 0x70, 0x69, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x73, 0x74, 0x61, 0x6b, 0x69, + 0x6e, 0x67, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x3b, 0x73, 0x74, 0x61, 0x6b, 0x69, + 0x6e, 0x67, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0xa2, 0x02, 0x03, 0x43, 0x53, 0x58, 0xaa, + 0x02, 0x16, 0x43, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x53, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, + 0x2e, 0x56, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0xca, 0x02, 0x16, 0x43, 0x6f, 0x73, 0x6d, 0x6f, + 0x73, 0x5c, 0x53, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x5c, 0x56, 0x31, 0x62, 0x65, 0x74, 0x61, + 0x31, 0xe2, 0x02, 0x22, 0x43, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x5c, 0x53, 0x74, 0x61, 0x6b, 0x69, + 0x6e, 0x67, 0x5c, 0x56, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, + 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x18, 0x43, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x3a, + 0x3a, 0x53, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x65, 0x74, 0x61, + 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/api/cosmos/staking/v1beta1/staking.pulsar.go b/api/cosmos/staking/v1beta1/staking.pulsar.go index 3b0e5cb37861..c2f9457ca822 100644 --- a/api/cosmos/staking/v1beta1/staking.pulsar.go +++ b/api/cosmos/staking/v1beta1/staking.pulsar.go @@ -1663,6 +1663,7 @@ var ( fd_Description_website protoreflect.FieldDescriptor fd_Description_security_contact protoreflect.FieldDescriptor fd_Description_details protoreflect.FieldDescriptor + fd_Description_metadata protoreflect.FieldDescriptor ) func init() { @@ -1673,6 +1674,7 @@ func init() { fd_Description_website = md_Description.Fields().ByName("website") fd_Description_security_contact = md_Description.Fields().ByName("security_contact") fd_Description_details = md_Description.Fields().ByName("details") + fd_Description_metadata = md_Description.Fields().ByName("metadata") } var _ protoreflect.Message = (*fastReflection_Description)(nil) @@ -1770,6 +1772,12 @@ func (x *fastReflection_Description) Range(f func(protoreflect.FieldDescriptor, return } } + if x.Metadata != nil { + value := protoreflect.ValueOfMessage(x.Metadata.ProtoReflect()) + if !f(fd_Description_metadata, value) { + return + } + } } // Has reports whether a field is populated. @@ -1795,6 +1803,8 @@ func (x *fastReflection_Description) Has(fd protoreflect.FieldDescriptor) bool { return x.SecurityContact != "" case "cosmos.staking.v1beta1.Description.details": return x.Details != "" + case "cosmos.staking.v1beta1.Description.metadata": + return x.Metadata != nil default: if fd.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.staking.v1beta1.Description")) @@ -1821,6 +1831,8 @@ func (x *fastReflection_Description) Clear(fd protoreflect.FieldDescriptor) { x.SecurityContact = "" case "cosmos.staking.v1beta1.Description.details": x.Details = "" + case "cosmos.staking.v1beta1.Description.metadata": + x.Metadata = nil default: if fd.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.staking.v1beta1.Description")) @@ -1852,6 +1864,9 @@ func (x *fastReflection_Description) Get(descriptor protoreflect.FieldDescriptor case "cosmos.staking.v1beta1.Description.details": value := x.Details return protoreflect.ValueOfString(value) + case "cosmos.staking.v1beta1.Description.metadata": + value := x.Metadata + return protoreflect.ValueOfMessage(value.ProtoReflect()) default: if descriptor.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.staking.v1beta1.Description")) @@ -1882,6 +1897,8 @@ func (x *fastReflection_Description) Set(fd protoreflect.FieldDescriptor, value x.SecurityContact = value.Interface().(string) case "cosmos.staking.v1beta1.Description.details": x.Details = value.Interface().(string) + case "cosmos.staking.v1beta1.Description.metadata": + x.Metadata = value.Message().Interface().(*Metadata) default: if fd.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.staking.v1beta1.Description")) @@ -1902,6 +1919,11 @@ func (x *fastReflection_Description) Set(fd protoreflect.FieldDescriptor, value // Mutable is a mutating operation and unsafe for concurrent use. func (x *fastReflection_Description) Mutable(fd protoreflect.FieldDescriptor) protoreflect.Value { switch fd.FullName() { + case "cosmos.staking.v1beta1.Description.metadata": + if x.Metadata == nil { + x.Metadata = new(Metadata) + } + return protoreflect.ValueOfMessage(x.Metadata.ProtoReflect()) case "cosmos.staking.v1beta1.Description.moniker": panic(fmt.Errorf("field moniker of message cosmos.staking.v1beta1.Description is not mutable")) case "cosmos.staking.v1beta1.Description.identity": @@ -1935,6 +1957,9 @@ func (x *fastReflection_Description) NewField(fd protoreflect.FieldDescriptor) p return protoreflect.ValueOfString("") case "cosmos.staking.v1beta1.Description.details": return protoreflect.ValueOfString("") + case "cosmos.staking.v1beta1.Description.metadata": + m := new(Metadata) + return protoreflect.ValueOfMessage(m.ProtoReflect()) default: if fd.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.staking.v1beta1.Description")) @@ -2024,6 +2049,10 @@ func (x *fastReflection_Description) ProtoMethods() *protoiface.Methods { if l > 0 { n += 1 + l + runtime.Sov(uint64(l)) } + if x.Metadata != nil { + l = options.Size(x.Metadata) + n += 1 + l + runtime.Sov(uint64(l)) + } if x.unknownFields != nil { n += len(x.unknownFields) } @@ -2053,6 +2082,20 @@ func (x *fastReflection_Description) ProtoMethods() *protoiface.Methods { i -= len(x.unknownFields) copy(dAtA[i:], x.unknownFields) } + if x.Metadata != nil { + encoded, err := options.Marshal(x.Metadata) + if err != nil { + return protoiface.MarshalOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Buf: input.Buf, + }, err + } + i -= len(encoded) + copy(dAtA[i:], encoded) + i = runtime.EncodeVarint(dAtA, i, uint64(len(encoded))) + i-- + dAtA[i] = 0x32 + } if len(x.Details) > 0 { i -= len(x.Details) copy(dAtA[i:], x.Details) @@ -2228,14 +2271,594 @@ func (x *fastReflection_Description) ProtoMethods() *protoiface.Methods { if postIndex < 0 { return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength } - if postIndex > l { + if postIndex > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + x.Website = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 4: + if wireType != 2 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field SecurityContact", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow + } + if iNdEx >= l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + if postIndex > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + x.SecurityContact = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 5: + if wireType != 2 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field Details", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow + } + if iNdEx >= l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + if postIndex > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + x.Details = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 6: + if wireType != 2 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field Metadata", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow + } + if iNdEx >= l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + if postIndex > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + if x.Metadata == nil { + x.Metadata = &Metadata{} + } + if err := options.Unmarshal(dAtA[iNdEx:postIndex], x.Metadata); err != nil { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := runtime.Skip(dAtA[iNdEx:]) + if err != nil { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + if (iNdEx + skippy) > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + if !options.DiscardUnknown { + x.unknownFields = append(x.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + } + iNdEx += skippy + } + } + + if iNdEx > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, nil + } + return &protoiface.Methods{ + NoUnkeyedLiterals: struct{}{}, + Flags: protoiface.SupportMarshalDeterministic | protoiface.SupportUnmarshalDiscardUnknown, + Size: size, + Marshal: marshal, + Unmarshal: unmarshal, + Merge: nil, + CheckInitialized: nil, + } +} + +var _ protoreflect.List = (*_Metadata_2_list)(nil) + +type _Metadata_2_list struct { + list *[]string +} + +func (x *_Metadata_2_list) Len() int { + if x.list == nil { + return 0 + } + return len(*x.list) +} + +func (x *_Metadata_2_list) Get(i int) protoreflect.Value { + return protoreflect.ValueOfString((*x.list)[i]) +} + +func (x *_Metadata_2_list) Set(i int, value protoreflect.Value) { + valueUnwrapped := value.String() + concreteValue := valueUnwrapped + (*x.list)[i] = concreteValue +} + +func (x *_Metadata_2_list) Append(value protoreflect.Value) { + valueUnwrapped := value.String() + concreteValue := valueUnwrapped + *x.list = append(*x.list, concreteValue) +} + +func (x *_Metadata_2_list) AppendMutable() protoreflect.Value { + panic(fmt.Errorf("AppendMutable can not be called on message Metadata at list field SocialHandleUris as it is not of Message kind")) +} + +func (x *_Metadata_2_list) Truncate(n int) { + *x.list = (*x.list)[:n] +} + +func (x *_Metadata_2_list) NewElement() protoreflect.Value { + v := "" + return protoreflect.ValueOfString(v) +} + +func (x *_Metadata_2_list) IsValid() bool { + return x.list != nil +} + +var ( + md_Metadata protoreflect.MessageDescriptor + fd_Metadata_profile_pic_uri protoreflect.FieldDescriptor + fd_Metadata_social_handle_uris protoreflect.FieldDescriptor +) + +func init() { + file_cosmos_staking_v1beta1_staking_proto_init() + md_Metadata = File_cosmos_staking_v1beta1_staking_proto.Messages().ByName("Metadata") + fd_Metadata_profile_pic_uri = md_Metadata.Fields().ByName("profile_pic_uri") + fd_Metadata_social_handle_uris = md_Metadata.Fields().ByName("social_handle_uris") +} + +var _ protoreflect.Message = (*fastReflection_Metadata)(nil) + +type fastReflection_Metadata Metadata + +func (x *Metadata) ProtoReflect() protoreflect.Message { + return (*fastReflection_Metadata)(x) +} + +func (x *Metadata) slowProtoReflect() protoreflect.Message { + mi := &file_cosmos_staking_v1beta1_staking_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +var _fastReflection_Metadata_messageType fastReflection_Metadata_messageType +var _ protoreflect.MessageType = fastReflection_Metadata_messageType{} + +type fastReflection_Metadata_messageType struct{} + +func (x fastReflection_Metadata_messageType) Zero() protoreflect.Message { + return (*fastReflection_Metadata)(nil) +} +func (x fastReflection_Metadata_messageType) New() protoreflect.Message { + return new(fastReflection_Metadata) +} +func (x fastReflection_Metadata_messageType) Descriptor() protoreflect.MessageDescriptor { + return md_Metadata +} + +// Descriptor returns message descriptor, which contains only the protobuf +// type information for the message. +func (x *fastReflection_Metadata) Descriptor() protoreflect.MessageDescriptor { + return md_Metadata +} + +// Type returns the message type, which encapsulates both Go and protobuf +// type information. If the Go type information is not needed, +// it is recommended that the message descriptor be used instead. +func (x *fastReflection_Metadata) Type() protoreflect.MessageType { + return _fastReflection_Metadata_messageType +} + +// New returns a newly allocated and mutable empty message. +func (x *fastReflection_Metadata) New() protoreflect.Message { + return new(fastReflection_Metadata) +} + +// Interface unwraps the message reflection interface and +// returns the underlying ProtoMessage interface. +func (x *fastReflection_Metadata) Interface() protoreflect.ProtoMessage { + return (*Metadata)(x) +} + +// Range iterates over every populated field in an undefined order, +// calling f for each field descriptor and value encountered. +// Range returns immediately if f returns false. +// While iterating, mutating operations may only be performed +// on the current field descriptor. +func (x *fastReflection_Metadata) Range(f func(protoreflect.FieldDescriptor, protoreflect.Value) bool) { + if x.ProfilePicUri != "" { + value := protoreflect.ValueOfString(x.ProfilePicUri) + if !f(fd_Metadata_profile_pic_uri, value) { + return + } + } + if len(x.SocialHandleUris) != 0 { + value := protoreflect.ValueOfList(&_Metadata_2_list{list: &x.SocialHandleUris}) + if !f(fd_Metadata_social_handle_uris, value) { + return + } + } +} + +// Has reports whether a field is populated. +// +// Some fields have the property of nullability where it is possible to +// distinguish between the default value of a field and whether the field +// was explicitly populated with the default value. Singular message fields, +// member fields of a oneof, and proto2 scalar fields are nullable. Such +// fields are populated only if explicitly set. +// +// In other cases (aside from the nullable cases above), +// a proto3 scalar field is populated if it contains a non-zero value, and +// a repeated field is populated if it is non-empty. +func (x *fastReflection_Metadata) Has(fd protoreflect.FieldDescriptor) bool { + switch fd.FullName() { + case "cosmos.staking.v1beta1.Metadata.profile_pic_uri": + return x.ProfilePicUri != "" + case "cosmos.staking.v1beta1.Metadata.social_handle_uris": + return len(x.SocialHandleUris) != 0 + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.staking.v1beta1.Metadata")) + } + panic(fmt.Errorf("message cosmos.staking.v1beta1.Metadata does not contain field %s", fd.FullName())) + } +} + +// Clear clears the field such that a subsequent Has call reports false. +// +// Clearing an extension field clears both the extension type and value +// associated with the given field number. +// +// Clear is a mutating operation and unsafe for concurrent use. +func (x *fastReflection_Metadata) Clear(fd protoreflect.FieldDescriptor) { + switch fd.FullName() { + case "cosmos.staking.v1beta1.Metadata.profile_pic_uri": + x.ProfilePicUri = "" + case "cosmos.staking.v1beta1.Metadata.social_handle_uris": + x.SocialHandleUris = nil + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.staking.v1beta1.Metadata")) + } + panic(fmt.Errorf("message cosmos.staking.v1beta1.Metadata does not contain field %s", fd.FullName())) + } +} + +// Get retrieves the value for a field. +// +// For unpopulated scalars, it returns the default value, where +// the default value of a bytes scalar is guaranteed to be a copy. +// For unpopulated composite types, it returns an empty, read-only view +// of the value; to obtain a mutable reference, use Mutable. +func (x *fastReflection_Metadata) Get(descriptor protoreflect.FieldDescriptor) protoreflect.Value { + switch descriptor.FullName() { + case "cosmos.staking.v1beta1.Metadata.profile_pic_uri": + value := x.ProfilePicUri + return protoreflect.ValueOfString(value) + case "cosmos.staking.v1beta1.Metadata.social_handle_uris": + if len(x.SocialHandleUris) == 0 { + return protoreflect.ValueOfList(&_Metadata_2_list{}) + } + listValue := &_Metadata_2_list{list: &x.SocialHandleUris} + return protoreflect.ValueOfList(listValue) + default: + if descriptor.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.staking.v1beta1.Metadata")) + } + panic(fmt.Errorf("message cosmos.staking.v1beta1.Metadata does not contain field %s", descriptor.FullName())) + } +} + +// Set stores the value for a field. +// +// For a field belonging to a oneof, it implicitly clears any other field +// that may be currently set within the same oneof. +// For extension fields, it implicitly stores the provided ExtensionType. +// When setting a composite type, it is unspecified whether the stored value +// aliases the source's memory in any way. If the composite value is an +// empty, read-only value, then it panics. +// +// Set is a mutating operation and unsafe for concurrent use. +func (x *fastReflection_Metadata) Set(fd protoreflect.FieldDescriptor, value protoreflect.Value) { + switch fd.FullName() { + case "cosmos.staking.v1beta1.Metadata.profile_pic_uri": + x.ProfilePicUri = value.Interface().(string) + case "cosmos.staking.v1beta1.Metadata.social_handle_uris": + lv := value.List() + clv := lv.(*_Metadata_2_list) + x.SocialHandleUris = *clv.list + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.staking.v1beta1.Metadata")) + } + panic(fmt.Errorf("message cosmos.staking.v1beta1.Metadata does not contain field %s", fd.FullName())) + } +} + +// Mutable returns a mutable reference to a composite type. +// +// If the field is unpopulated, it may allocate a composite value. +// For a field belonging to a oneof, it implicitly clears any other field +// that may be currently set within the same oneof. +// For extension fields, it implicitly stores the provided ExtensionType +// if not already stored. +// It panics if the field does not contain a composite type. +// +// Mutable is a mutating operation and unsafe for concurrent use. +func (x *fastReflection_Metadata) Mutable(fd protoreflect.FieldDescriptor) protoreflect.Value { + switch fd.FullName() { + case "cosmos.staking.v1beta1.Metadata.social_handle_uris": + if x.SocialHandleUris == nil { + x.SocialHandleUris = []string{} + } + value := &_Metadata_2_list{list: &x.SocialHandleUris} + return protoreflect.ValueOfList(value) + case "cosmos.staking.v1beta1.Metadata.profile_pic_uri": + panic(fmt.Errorf("field profile_pic_uri of message cosmos.staking.v1beta1.Metadata is not mutable")) + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.staking.v1beta1.Metadata")) + } + panic(fmt.Errorf("message cosmos.staking.v1beta1.Metadata does not contain field %s", fd.FullName())) + } +} + +// NewField returns a new value that is assignable to the field +// for the given descriptor. For scalars, this returns the default value. +// For lists, maps, and messages, this returns a new, empty, mutable value. +func (x *fastReflection_Metadata) NewField(fd protoreflect.FieldDescriptor) protoreflect.Value { + switch fd.FullName() { + case "cosmos.staking.v1beta1.Metadata.profile_pic_uri": + return protoreflect.ValueOfString("") + case "cosmos.staking.v1beta1.Metadata.social_handle_uris": + list := []string{} + return protoreflect.ValueOfList(&_Metadata_2_list{list: &list}) + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.staking.v1beta1.Metadata")) + } + panic(fmt.Errorf("message cosmos.staking.v1beta1.Metadata does not contain field %s", fd.FullName())) + } +} + +// WhichOneof reports which field within the oneof is populated, +// returning nil if none are populated. +// It panics if the oneof descriptor does not belong to this message. +func (x *fastReflection_Metadata) WhichOneof(d protoreflect.OneofDescriptor) protoreflect.FieldDescriptor { + switch d.FullName() { + default: + panic(fmt.Errorf("%s is not a oneof field in cosmos.staking.v1beta1.Metadata", d.FullName())) + } + panic("unreachable") +} + +// GetUnknown retrieves the entire list of unknown fields. +// The caller may only mutate the contents of the RawFields +// if the mutated bytes are stored back into the message with SetUnknown. +func (x *fastReflection_Metadata) GetUnknown() protoreflect.RawFields { + return x.unknownFields +} + +// SetUnknown stores an entire list of unknown fields. +// The raw fields must be syntactically valid according to the wire format. +// An implementation may panic if this is not the case. +// Once stored, the caller must not mutate the content of the RawFields. +// An empty RawFields may be passed to clear the fields. +// +// SetUnknown is a mutating operation and unsafe for concurrent use. +func (x *fastReflection_Metadata) SetUnknown(fields protoreflect.RawFields) { + x.unknownFields = fields +} + +// IsValid reports whether the message is valid. +// +// An invalid message is an empty, read-only value. +// +// An invalid message often corresponds to a nil pointer of the concrete +// message type, but the details are implementation dependent. +// Validity is not part of the protobuf data model, and may not +// be preserved in marshaling or other operations. +func (x *fastReflection_Metadata) IsValid() bool { + return x != nil +} + +// ProtoMethods returns optional fastReflectionFeature-path implementations of various operations. +// This method may return nil. +// +// The returned methods type is identical to +// "google.golang.org/protobuf/runtime/protoiface".Methods. +// Consult the protoiface package documentation for details. +func (x *fastReflection_Metadata) ProtoMethods() *protoiface.Methods { + size := func(input protoiface.SizeInput) protoiface.SizeOutput { + x := input.Message.Interface().(*Metadata) + if x == nil { + return protoiface.SizeOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Size: 0, + } + } + options := runtime.SizeInputToOptions(input) + _ = options + var n int + var l int + _ = l + l = len(x.ProfilePicUri) + if l > 0 { + n += 1 + l + runtime.Sov(uint64(l)) + } + if len(x.SocialHandleUris) > 0 { + for _, s := range x.SocialHandleUris { + l = len(s) + n += 1 + l + runtime.Sov(uint64(l)) + } + } + if x.unknownFields != nil { + n += len(x.unknownFields) + } + return protoiface.SizeOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Size: n, + } + } + + marshal := func(input protoiface.MarshalInput) (protoiface.MarshalOutput, error) { + x := input.Message.Interface().(*Metadata) + if x == nil { + return protoiface.MarshalOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Buf: input.Buf, + }, nil + } + options := runtime.MarshalInputToOptions(input) + _ = options + size := options.Size(x) + dAtA := make([]byte, size) + i := len(dAtA) + _ = i + var l int + _ = l + if x.unknownFields != nil { + i -= len(x.unknownFields) + copy(dAtA[i:], x.unknownFields) + } + if len(x.SocialHandleUris) > 0 { + for iNdEx := len(x.SocialHandleUris) - 1; iNdEx >= 0; iNdEx-- { + i -= len(x.SocialHandleUris[iNdEx]) + copy(dAtA[i:], x.SocialHandleUris[iNdEx]) + i = runtime.EncodeVarint(dAtA, i, uint64(len(x.SocialHandleUris[iNdEx]))) + i-- + dAtA[i] = 0x12 + } + } + if len(x.ProfilePicUri) > 0 { + i -= len(x.ProfilePicUri) + copy(dAtA[i:], x.ProfilePicUri) + i = runtime.EncodeVarint(dAtA, i, uint64(len(x.ProfilePicUri))) + i-- + dAtA[i] = 0xa + } + if input.Buf != nil { + input.Buf = append(input.Buf, dAtA...) + } else { + input.Buf = dAtA + } + return protoiface.MarshalOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Buf: input.Buf, + }, nil + } + unmarshal := func(input protoiface.UnmarshalInput) (protoiface.UnmarshalOutput, error) { + x := input.Message.Interface().(*Metadata) + if x == nil { + return protoiface.UnmarshalOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Flags: input.Flags, + }, nil + } + options := runtime.UnmarshalInputToOptions(input) + _ = options + dAtA := input.Buf + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow + } + if iNdEx >= l { return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF } - x.Website = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 4: + 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 protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: Metadata: wiretype end group for non-group") + } + if fieldNum <= 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: Metadata: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: if wireType != 2 { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field SecurityContact", wireType) + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field ProfilePicUri", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -2263,11 +2886,11 @@ func (x *fastReflection_Description) ProtoMethods() *protoiface.Methods { if postIndex > l { return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF } - x.SecurityContact = string(dAtA[iNdEx:postIndex]) + x.ProfilePicUri = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex - case 5: + case 2: if wireType != 2 { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field Details", wireType) + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field SocialHandleUris", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -2295,7 +2918,7 @@ func (x *fastReflection_Description) ProtoMethods() *protoiface.Methods { if postIndex > l { return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF } - x.Details = string(dAtA[iNdEx:postIndex]) + x.SocialHandleUris = append(x.SocialHandleUris, string(dAtA[iNdEx:postIndex])) iNdEx = postIndex default: iNdEx = preIndex @@ -2422,7 +3045,7 @@ func (x *Validator) ProtoReflect() protoreflect.Message { } func (x *Validator) slowProtoReflect() protoreflect.Message { - mi := &file_cosmos_staking_v1beta1_staking_proto_msgTypes[4] + mi := &file_cosmos_staking_v1beta1_staking_proto_msgTypes[5] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3704,7 +4327,7 @@ func (x *ValAddresses) ProtoReflect() protoreflect.Message { } func (x *ValAddresses) slowProtoReflect() protoreflect.Message { - mi := &file_cosmos_staking_v1beta1_staking_proto_msgTypes[5] + mi := &file_cosmos_staking_v1beta1_staking_proto_msgTypes[6] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4140,7 +4763,7 @@ func (x *DVPair) ProtoReflect() protoreflect.Message { } func (x *DVPair) slowProtoReflect() protoreflect.Message { - mi := &file_cosmos_staking_v1beta1_staking_proto_msgTypes[6] + mi := &file_cosmos_staking_v1beta1_staking_proto_msgTypes[7] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4673,7 +5296,7 @@ func (x *DVPairs) ProtoReflect() protoreflect.Message { } func (x *DVPairs) slowProtoReflect() protoreflect.Message { - mi := &file_cosmos_staking_v1beta1_staking_proto_msgTypes[7] + mi := &file_cosmos_staking_v1beta1_staking_proto_msgTypes[8] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5120,7 +5743,7 @@ func (x *DVVTriplet) ProtoReflect() protoreflect.Message { } func (x *DVVTriplet) slowProtoReflect() protoreflect.Message { - mi := &file_cosmos_staking_v1beta1_staking_proto_msgTypes[8] + mi := &file_cosmos_staking_v1beta1_staking_proto_msgTypes[9] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5715,7 +6338,7 @@ func (x *DVVTriplets) ProtoReflect() protoreflect.Message { } func (x *DVVTriplets) slowProtoReflect() protoreflect.Message { - mi := &file_cosmos_staking_v1beta1_staking_proto_msgTypes[9] + mi := &file_cosmos_staking_v1beta1_staking_proto_msgTypes[10] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6162,7 +6785,7 @@ func (x *Delegation) ProtoReflect() protoreflect.Message { } func (x *Delegation) slowProtoReflect() protoreflect.Message { - mi := &file_cosmos_staking_v1beta1_staking_proto_msgTypes[10] + mi := &file_cosmos_staking_v1beta1_staking_proto_msgTypes[11] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6761,7 +7384,7 @@ func (x *UnbondingDelegation) ProtoReflect() protoreflect.Message { } func (x *UnbondingDelegation) slowProtoReflect() protoreflect.Message { - mi := &file_cosmos_staking_v1beta1_staking_proto_msgTypes[11] + mi := &file_cosmos_staking_v1beta1_staking_proto_msgTypes[12] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7338,7 +7961,7 @@ func (x *UnbondingDelegationEntry) ProtoReflect() protoreflect.Message { } func (x *UnbondingDelegationEntry) slowProtoReflect() protoreflect.Message { - mi := &file_cosmos_staking_v1beta1_staking_proto_msgTypes[12] + mi := &file_cosmos_staking_v1beta1_staking_proto_msgTypes[13] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8045,7 +8668,7 @@ func (x *RedelegationEntry) ProtoReflect() protoreflect.Message { } func (x *RedelegationEntry) slowProtoReflect() protoreflect.Message { - mi := &file_cosmos_staking_v1beta1_staking_proto_msgTypes[13] + mi := &file_cosmos_staking_v1beta1_staking_proto_msgTypes[14] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8799,7 +9422,7 @@ func (x *Redelegation) ProtoReflect() protoreflect.Message { } func (x *Redelegation) slowProtoReflect() protoreflect.Message { - mi := &file_cosmos_staking_v1beta1_staking_proto_msgTypes[14] + mi := &file_cosmos_staking_v1beta1_staking_proto_msgTypes[15] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9440,7 +10063,7 @@ func (x *Params) ProtoReflect() protoreflect.Message { } func (x *Params) slowProtoReflect() protoreflect.Message { - mi := &file_cosmos_staking_v1beta1_staking_proto_msgTypes[15] + mi := &file_cosmos_staking_v1beta1_staking_proto_msgTypes[16] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10216,7 +10839,7 @@ func (x *DelegationResponse) ProtoReflect() protoreflect.Message { } func (x *DelegationResponse) slowProtoReflect() protoreflect.Message { - mi := &file_cosmos_staking_v1beta1_staking_proto_msgTypes[16] + mi := &file_cosmos_staking_v1beta1_staking_proto_msgTypes[17] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10730,7 +11353,7 @@ func (x *RedelegationEntryResponse) ProtoReflect() protoreflect.Message { } func (x *RedelegationEntryResponse) slowProtoReflect() protoreflect.Message { - mi := &file_cosmos_staking_v1beta1_staking_proto_msgTypes[17] + mi := &file_cosmos_staking_v1beta1_staking_proto_msgTypes[18] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11280,7 +11903,7 @@ func (x *RedelegationResponse) ProtoReflect() protoreflect.Message { } func (x *RedelegationResponse) slowProtoReflect() protoreflect.Message { - mi := &file_cosmos_staking_v1beta1_staking_proto_msgTypes[18] + mi := &file_cosmos_staking_v1beta1_staking_proto_msgTypes[19] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11802,7 +12425,7 @@ func (x *Pool) ProtoReflect() protoreflect.Message { } func (x *Pool) slowProtoReflect() protoreflect.Message { - mi := &file_cosmos_staking_v1beta1_staking_proto_msgTypes[19] + mi := &file_cosmos_staking_v1beta1_staking_proto_msgTypes[20] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12335,7 +12958,7 @@ func (x *ValidatorUpdates) ProtoReflect() protoreflect.Message { } func (x *ValidatorUpdates) slowProtoReflect() protoreflect.Message { - mi := &file_cosmos_staking_v1beta1_staking_proto_msgTypes[20] + mi := &file_cosmos_staking_v1beta1_staking_proto_msgTypes[21] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12786,7 +13409,7 @@ func (x *ConsPubKeyRotationHistory) ProtoReflect() protoreflect.Message { } func (x *ConsPubKeyRotationHistory) slowProtoReflect() protoreflect.Message { - mi := &file_cosmos_staking_v1beta1_staking_proto_msgTypes[21] + mi := &file_cosmos_staking_v1beta1_staking_proto_msgTypes[22] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -13531,7 +14154,7 @@ func (x *ValAddrsOfRotatedConsKeys) ProtoReflect() protoreflect.Message { } func (x *ValAddrsOfRotatedConsKeys) slowProtoReflect() protoreflect.Message { - mi := &file_cosmos_staking_v1beta1_staking_proto_msgTypes[22] + mi := &file_cosmos_staking_v1beta1_staking_proto_msgTypes[23] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -14235,6 +14858,8 @@ type Description struct { SecurityContact string `protobuf:"bytes,4,opt,name=security_contact,json=securityContact,proto3" json:"security_contact,omitempty"` // details define other optional details. Details string `protobuf:"bytes,5,opt,name=details,proto3" json:"details,omitempty"` + // metadata defines extra information about the validator. + Metadata *Metadata `protobuf:"bytes,6,opt,name=metadata,proto3" json:"metadata,omitempty"` } func (x *Description) Reset() { @@ -14292,6 +14917,59 @@ func (x *Description) GetDetails() string { return "" } +func (x *Description) GetMetadata() *Metadata { + if x != nil { + return x.Metadata + } + return nil +} + +// Metadata defines extra information about the validator. +type Metadata struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // profile_pic_uri defines a link to the validator profile picture. + ProfilePicUri string `protobuf:"bytes,1,opt,name=profile_pic_uri,json=profilePicUri,proto3" json:"profile_pic_uri,omitempty"` + // social_handle_uris defines a string array of uris to the validator's social handles. + SocialHandleUris []string `protobuf:"bytes,2,rep,name=social_handle_uris,json=socialHandleUris,proto3" json:"social_handle_uris,omitempty"` +} + +func (x *Metadata) Reset() { + *x = Metadata{} + if protoimpl.UnsafeEnabled { + mi := &file_cosmos_staking_v1beta1_staking_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Metadata) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Metadata) ProtoMessage() {} + +// Deprecated: Use Metadata.ProtoReflect.Descriptor instead. +func (*Metadata) Descriptor() ([]byte, []int) { + return file_cosmos_staking_v1beta1_staking_proto_rawDescGZIP(), []int{4} +} + +func (x *Metadata) GetProfilePicUri() string { + if x != nil { + return x.ProfilePicUri + } + return "" +} + +func (x *Metadata) GetSocialHandleUris() []string { + if x != nil { + return x.SocialHandleUris + } + return nil +} + // Validator defines a validator, together with the total amount of the // Validator's bond shares and their exchange rate to coins. Slashing results in // a decrease in the exchange rate, allowing correct calculation of future @@ -14336,7 +15014,7 @@ type Validator struct { func (x *Validator) Reset() { *x = Validator{} if protoimpl.UnsafeEnabled { - mi := &file_cosmos_staking_v1beta1_staking_proto_msgTypes[4] + mi := &file_cosmos_staking_v1beta1_staking_proto_msgTypes[5] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -14350,7 +15028,7 @@ func (*Validator) ProtoMessage() {} // Deprecated: Use Validator.ProtoReflect.Descriptor instead. func (*Validator) Descriptor() ([]byte, []int) { - return file_cosmos_staking_v1beta1_staking_proto_rawDescGZIP(), []int{4} + return file_cosmos_staking_v1beta1_staking_proto_rawDescGZIP(), []int{5} } func (x *Validator) GetOperatorAddress() string { @@ -14456,7 +15134,7 @@ type ValAddresses struct { func (x *ValAddresses) Reset() { *x = ValAddresses{} if protoimpl.UnsafeEnabled { - mi := &file_cosmos_staking_v1beta1_staking_proto_msgTypes[5] + mi := &file_cosmos_staking_v1beta1_staking_proto_msgTypes[6] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -14470,7 +15148,7 @@ func (*ValAddresses) ProtoMessage() {} // Deprecated: Use ValAddresses.ProtoReflect.Descriptor instead. func (*ValAddresses) Descriptor() ([]byte, []int) { - return file_cosmos_staking_v1beta1_staking_proto_rawDescGZIP(), []int{5} + return file_cosmos_staking_v1beta1_staking_proto_rawDescGZIP(), []int{6} } func (x *ValAddresses) GetAddresses() []string { @@ -14495,7 +15173,7 @@ type DVPair struct { func (x *DVPair) Reset() { *x = DVPair{} if protoimpl.UnsafeEnabled { - mi := &file_cosmos_staking_v1beta1_staking_proto_msgTypes[6] + mi := &file_cosmos_staking_v1beta1_staking_proto_msgTypes[7] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -14509,7 +15187,7 @@ func (*DVPair) ProtoMessage() {} // Deprecated: Use DVPair.ProtoReflect.Descriptor instead. func (*DVPair) Descriptor() ([]byte, []int) { - return file_cosmos_staking_v1beta1_staking_proto_rawDescGZIP(), []int{6} + return file_cosmos_staking_v1beta1_staking_proto_rawDescGZIP(), []int{7} } func (x *DVPair) GetDelegatorAddress() string { @@ -14538,7 +15216,7 @@ type DVPairs struct { func (x *DVPairs) Reset() { *x = DVPairs{} if protoimpl.UnsafeEnabled { - mi := &file_cosmos_staking_v1beta1_staking_proto_msgTypes[7] + mi := &file_cosmos_staking_v1beta1_staking_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -14552,7 +15230,7 @@ func (*DVPairs) ProtoMessage() {} // Deprecated: Use DVPairs.ProtoReflect.Descriptor instead. func (*DVPairs) Descriptor() ([]byte, []int) { - return file_cosmos_staking_v1beta1_staking_proto_rawDescGZIP(), []int{7} + return file_cosmos_staking_v1beta1_staking_proto_rawDescGZIP(), []int{8} } func (x *DVPairs) GetPairs() []*DVPair { @@ -14579,7 +15257,7 @@ type DVVTriplet struct { func (x *DVVTriplet) Reset() { *x = DVVTriplet{} if protoimpl.UnsafeEnabled { - mi := &file_cosmos_staking_v1beta1_staking_proto_msgTypes[8] + mi := &file_cosmos_staking_v1beta1_staking_proto_msgTypes[9] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -14593,7 +15271,7 @@ func (*DVVTriplet) ProtoMessage() {} // Deprecated: Use DVVTriplet.ProtoReflect.Descriptor instead. func (*DVVTriplet) Descriptor() ([]byte, []int) { - return file_cosmos_staking_v1beta1_staking_proto_rawDescGZIP(), []int{8} + return file_cosmos_staking_v1beta1_staking_proto_rawDescGZIP(), []int{9} } func (x *DVVTriplet) GetDelegatorAddress() string { @@ -14629,7 +15307,7 @@ type DVVTriplets struct { func (x *DVVTriplets) Reset() { *x = DVVTriplets{} if protoimpl.UnsafeEnabled { - mi := &file_cosmos_staking_v1beta1_staking_proto_msgTypes[9] + mi := &file_cosmos_staking_v1beta1_staking_proto_msgTypes[10] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -14643,7 +15321,7 @@ func (*DVVTriplets) ProtoMessage() {} // Deprecated: Use DVVTriplets.ProtoReflect.Descriptor instead. func (*DVVTriplets) Descriptor() ([]byte, []int) { - return file_cosmos_staking_v1beta1_staking_proto_rawDescGZIP(), []int{9} + return file_cosmos_staking_v1beta1_staking_proto_rawDescGZIP(), []int{10} } func (x *DVVTriplets) GetTriplets() []*DVVTriplet { @@ -14672,7 +15350,7 @@ type Delegation struct { func (x *Delegation) Reset() { *x = Delegation{} if protoimpl.UnsafeEnabled { - mi := &file_cosmos_staking_v1beta1_staking_proto_msgTypes[10] + mi := &file_cosmos_staking_v1beta1_staking_proto_msgTypes[11] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -14686,7 +15364,7 @@ func (*Delegation) ProtoMessage() {} // Deprecated: Use Delegation.ProtoReflect.Descriptor instead. func (*Delegation) Descriptor() ([]byte, []int) { - return file_cosmos_staking_v1beta1_staking_proto_rawDescGZIP(), []int{10} + return file_cosmos_staking_v1beta1_staking_proto_rawDescGZIP(), []int{11} } func (x *Delegation) GetDelegatorAddress() string { @@ -14728,7 +15406,7 @@ type UnbondingDelegation struct { func (x *UnbondingDelegation) Reset() { *x = UnbondingDelegation{} if protoimpl.UnsafeEnabled { - mi := &file_cosmos_staking_v1beta1_staking_proto_msgTypes[11] + mi := &file_cosmos_staking_v1beta1_staking_proto_msgTypes[12] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -14742,7 +15420,7 @@ func (*UnbondingDelegation) ProtoMessage() {} // Deprecated: Use UnbondingDelegation.ProtoReflect.Descriptor instead. func (*UnbondingDelegation) Descriptor() ([]byte, []int) { - return file_cosmos_staking_v1beta1_staking_proto_rawDescGZIP(), []int{11} + return file_cosmos_staking_v1beta1_staking_proto_rawDescGZIP(), []int{12} } func (x *UnbondingDelegation) GetDelegatorAddress() string { @@ -14789,7 +15467,7 @@ type UnbondingDelegationEntry struct { func (x *UnbondingDelegationEntry) Reset() { *x = UnbondingDelegationEntry{} if protoimpl.UnsafeEnabled { - mi := &file_cosmos_staking_v1beta1_staking_proto_msgTypes[12] + mi := &file_cosmos_staking_v1beta1_staking_proto_msgTypes[13] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -14803,7 +15481,7 @@ func (*UnbondingDelegationEntry) ProtoMessage() {} // Deprecated: Use UnbondingDelegationEntry.ProtoReflect.Descriptor instead. func (*UnbondingDelegationEntry) Descriptor() ([]byte, []int) { - return file_cosmos_staking_v1beta1_staking_proto_rawDescGZIP(), []int{12} + return file_cosmos_staking_v1beta1_staking_proto_rawDescGZIP(), []int{13} } func (x *UnbondingDelegationEntry) GetCreationHeight() int64 { @@ -14871,7 +15549,7 @@ type RedelegationEntry struct { func (x *RedelegationEntry) Reset() { *x = RedelegationEntry{} if protoimpl.UnsafeEnabled { - mi := &file_cosmos_staking_v1beta1_staking_proto_msgTypes[13] + mi := &file_cosmos_staking_v1beta1_staking_proto_msgTypes[14] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -14885,7 +15563,7 @@ func (*RedelegationEntry) ProtoMessage() {} // Deprecated: Use RedelegationEntry.ProtoReflect.Descriptor instead. func (*RedelegationEntry) Descriptor() ([]byte, []int) { - return file_cosmos_staking_v1beta1_staking_proto_rawDescGZIP(), []int{13} + return file_cosmos_staking_v1beta1_staking_proto_rawDescGZIP(), []int{14} } func (x *RedelegationEntry) GetCreationHeight() int64 { @@ -14950,7 +15628,7 @@ type Redelegation struct { func (x *Redelegation) Reset() { *x = Redelegation{} if protoimpl.UnsafeEnabled { - mi := &file_cosmos_staking_v1beta1_staking_proto_msgTypes[14] + mi := &file_cosmos_staking_v1beta1_staking_proto_msgTypes[15] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -14964,7 +15642,7 @@ func (*Redelegation) ProtoMessage() {} // Deprecated: Use Redelegation.ProtoReflect.Descriptor instead. func (*Redelegation) Descriptor() ([]byte, []int) { - return file_cosmos_staking_v1beta1_staking_proto_rawDescGZIP(), []int{14} + return file_cosmos_staking_v1beta1_staking_proto_rawDescGZIP(), []int{15} } func (x *Redelegation) GetDelegatorAddress() string { @@ -15023,7 +15701,7 @@ type Params struct { func (x *Params) Reset() { *x = Params{} if protoimpl.UnsafeEnabled { - mi := &file_cosmos_staking_v1beta1_staking_proto_msgTypes[15] + mi := &file_cosmos_staking_v1beta1_staking_proto_msgTypes[16] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -15037,7 +15715,7 @@ func (*Params) ProtoMessage() {} // Deprecated: Use Params.ProtoReflect.Descriptor instead. func (*Params) Descriptor() ([]byte, []int) { - return file_cosmos_staking_v1beta1_staking_proto_rawDescGZIP(), []int{15} + return file_cosmos_staking_v1beta1_staking_proto_rawDescGZIP(), []int{16} } func (x *Params) GetUnbondingTime() *durationpb.Duration { @@ -15104,7 +15782,7 @@ type DelegationResponse struct { func (x *DelegationResponse) Reset() { *x = DelegationResponse{} if protoimpl.UnsafeEnabled { - mi := &file_cosmos_staking_v1beta1_staking_proto_msgTypes[16] + mi := &file_cosmos_staking_v1beta1_staking_proto_msgTypes[17] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -15118,7 +15796,7 @@ func (*DelegationResponse) ProtoMessage() {} // Deprecated: Use DelegationResponse.ProtoReflect.Descriptor instead. func (*DelegationResponse) Descriptor() ([]byte, []int) { - return file_cosmos_staking_v1beta1_staking_proto_rawDescGZIP(), []int{16} + return file_cosmos_staking_v1beta1_staking_proto_rawDescGZIP(), []int{17} } func (x *DelegationResponse) GetDelegation() *Delegation { @@ -15150,7 +15828,7 @@ type RedelegationEntryResponse struct { func (x *RedelegationEntryResponse) Reset() { *x = RedelegationEntryResponse{} if protoimpl.UnsafeEnabled { - mi := &file_cosmos_staking_v1beta1_staking_proto_msgTypes[17] + mi := &file_cosmos_staking_v1beta1_staking_proto_msgTypes[18] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -15164,7 +15842,7 @@ func (*RedelegationEntryResponse) ProtoMessage() {} // Deprecated: Use RedelegationEntryResponse.ProtoReflect.Descriptor instead. func (*RedelegationEntryResponse) Descriptor() ([]byte, []int) { - return file_cosmos_staking_v1beta1_staking_proto_rawDescGZIP(), []int{17} + return file_cosmos_staking_v1beta1_staking_proto_rawDescGZIP(), []int{18} } func (x *RedelegationEntryResponse) GetRedelegationEntry() *RedelegationEntry { @@ -15196,7 +15874,7 @@ type RedelegationResponse struct { func (x *RedelegationResponse) Reset() { *x = RedelegationResponse{} if protoimpl.UnsafeEnabled { - mi := &file_cosmos_staking_v1beta1_staking_proto_msgTypes[18] + mi := &file_cosmos_staking_v1beta1_staking_proto_msgTypes[19] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -15210,7 +15888,7 @@ func (*RedelegationResponse) ProtoMessage() {} // Deprecated: Use RedelegationResponse.ProtoReflect.Descriptor instead. func (*RedelegationResponse) Descriptor() ([]byte, []int) { - return file_cosmos_staking_v1beta1_staking_proto_rawDescGZIP(), []int{18} + return file_cosmos_staking_v1beta1_staking_proto_rawDescGZIP(), []int{19} } func (x *RedelegationResponse) GetRedelegation() *Redelegation { @@ -15241,7 +15919,7 @@ type Pool struct { func (x *Pool) Reset() { *x = Pool{} if protoimpl.UnsafeEnabled { - mi := &file_cosmos_staking_v1beta1_staking_proto_msgTypes[19] + mi := &file_cosmos_staking_v1beta1_staking_proto_msgTypes[20] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -15255,7 +15933,7 @@ func (*Pool) ProtoMessage() {} // Deprecated: Use Pool.ProtoReflect.Descriptor instead. func (*Pool) Descriptor() ([]byte, []int) { - return file_cosmos_staking_v1beta1_staking_proto_rawDescGZIP(), []int{19} + return file_cosmos_staking_v1beta1_staking_proto_rawDescGZIP(), []int{20} } func (x *Pool) GetNotBondedTokens() string { @@ -15287,7 +15965,7 @@ type ValidatorUpdates struct { func (x *ValidatorUpdates) Reset() { *x = ValidatorUpdates{} if protoimpl.UnsafeEnabled { - mi := &file_cosmos_staking_v1beta1_staking_proto_msgTypes[20] + mi := &file_cosmos_staking_v1beta1_staking_proto_msgTypes[21] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -15301,7 +15979,7 @@ func (*ValidatorUpdates) ProtoMessage() {} // Deprecated: Use ValidatorUpdates.ProtoReflect.Descriptor instead. func (*ValidatorUpdates) Descriptor() ([]byte, []int) { - return file_cosmos_staking_v1beta1_staking_proto_rawDescGZIP(), []int{20} + return file_cosmos_staking_v1beta1_staking_proto_rawDescGZIP(), []int{21} } func (x *ValidatorUpdates) GetUpdates() []*v11.ValidatorUpdate { @@ -15332,7 +16010,7 @@ type ConsPubKeyRotationHistory struct { func (x *ConsPubKeyRotationHistory) Reset() { *x = ConsPubKeyRotationHistory{} if protoimpl.UnsafeEnabled { - mi := &file_cosmos_staking_v1beta1_staking_proto_msgTypes[21] + mi := &file_cosmos_staking_v1beta1_staking_proto_msgTypes[22] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -15346,7 +16024,7 @@ func (*ConsPubKeyRotationHistory) ProtoMessage() {} // Deprecated: Use ConsPubKeyRotationHistory.ProtoReflect.Descriptor instead. func (*ConsPubKeyRotationHistory) Descriptor() ([]byte, []int) { - return file_cosmos_staking_v1beta1_staking_proto_rawDescGZIP(), []int{21} + return file_cosmos_staking_v1beta1_staking_proto_rawDescGZIP(), []int{22} } func (x *ConsPubKeyRotationHistory) GetOperatorAddress() []byte { @@ -15397,7 +16075,7 @@ type ValAddrsOfRotatedConsKeys struct { func (x *ValAddrsOfRotatedConsKeys) Reset() { *x = ValAddrsOfRotatedConsKeys{} if protoimpl.UnsafeEnabled { - mi := &file_cosmos_staking_v1beta1_staking_proto_msgTypes[22] + mi := &file_cosmos_staking_v1beta1_staking_proto_msgTypes[23] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -15411,7 +16089,7 @@ func (*ValAddrsOfRotatedConsKeys) ProtoMessage() {} // Deprecated: Use ValAddrsOfRotatedConsKeys.ProtoReflect.Descriptor instead. func (*ValAddrsOfRotatedConsKeys) Descriptor() ([]byte, []int) { - return file_cosmos_staking_v1beta1_staking_proto_rawDescGZIP(), []int{22} + return file_cosmos_staking_v1beta1_staking_proto_rawDescGZIP(), []int{23} } func (x *ValAddrsOfRotatedConsKeys) GetAddresses() [][]byte { @@ -15427,23 +16105,23 @@ var file_cosmos_staking_v1beta1_staking_proto_rawDesc = []byte{ 0x0a, 0x24, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x16, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x73, - 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x1a, 0x14, - 0x67, 0x6f, 0x67, 0x6f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x6f, 0x67, 0x6f, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x19, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x61, 0x6e, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, - 0x1e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2f, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, - 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x1a, 0x19, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x63, - 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1e, 0x63, 0x6f, 0x73, - 0x6d, 0x6f, 0x73, 0x2f, 0x62, 0x61, 0x73, 0x65, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x2f, 0x63, 0x6f, 0x69, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x11, 0x61, 0x6d, 0x69, - 0x6e, 0x6f, 0x2f, 0x61, 0x6d, 0x69, 0x6e, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1d, - 0x63, 0x6f, 0x6d, 0x65, 0x74, 0x62, 0x66, 0x74, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x76, - 0x31, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1c, 0x63, - 0x6f, 0x6d, 0x65, 0x74, 0x62, 0x66, 0x74, 0x2f, 0x61, 0x62, 0x63, 0x69, 0x2f, 0x76, 0x31, 0x2f, - 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x98, 0x01, 0x0a, 0x0e, + 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x1a, 0x11, + 0x61, 0x6d, 0x69, 0x6e, 0x6f, 0x2f, 0x61, 0x6d, 0x69, 0x6e, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x1a, 0x1c, 0x63, 0x6f, 0x6d, 0x65, 0x74, 0x62, 0x66, 0x74, 0x2f, 0x61, 0x62, 0x63, 0x69, + 0x2f, 0x76, 0x31, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, + 0x1d, 0x63, 0x6f, 0x6d, 0x65, 0x74, 0x62, 0x66, 0x74, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, + 0x76, 0x31, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1e, + 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x62, 0x61, 0x73, 0x65, 0x2f, 0x76, 0x31, 0x62, 0x65, + 0x74, 0x61, 0x31, 0x2f, 0x63, 0x6f, 0x69, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x19, + 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x63, 0x6f, 0x73, + 0x6d, 0x6f, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x14, 0x67, 0x6f, 0x67, 0x6f, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x6f, 0x67, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, + 0x19, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x2f, 0x61, 0x6e, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x64, 0x75, 0x72, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, + 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x98, 0x01, 0x0a, 0x0e, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x69, 0x63, 0x61, 0x6c, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x3c, 0x0a, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x63, 0x6f, 0x6d, 0x65, 0x74, 0x62, 0x66, 0x74, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, @@ -15483,7 +16161,7 @@ var file_cosmos_staking_v1beta1_staking_proto_rawDesc = []byte{ 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x42, 0x0d, 0xc8, 0xde, 0x1f, 0x00, 0x90, 0xdf, 0x1f, 0x01, 0xa8, 0xe7, 0xb0, 0x2a, 0x01, 0x52, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x3a, 0x04, 0xe8, - 0xa0, 0x1f, 0x01, 0x22, 0xa8, 0x01, 0x0a, 0x0b, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, + 0xa0, 0x1f, 0x01, 0x22, 0xf1, 0x01, 0x0a, 0x0b, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x6f, 0x6e, 0x69, 0x6b, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x6f, 0x6e, 0x69, 0x6b, 0x65, 0x72, 0x12, 0x1a, 0x0a, 0x08, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, @@ -15493,361 +16171,372 @@ var file_cosmos_staking_v1beta1_staking_proto_rawDesc = []byte{ 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x63, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x63, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x07, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x3a, 0x04, 0xe8, 0xa0, 0x1f, 0x01, 0x22, 0x9d, - 0x07, 0x0a, 0x09, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x12, 0x43, 0x0a, 0x10, - 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xd2, 0xb4, 0x2d, 0x14, 0x63, 0x6f, 0x73, 0x6d, - 0x6f, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, - 0x52, 0x0f, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, - 0x73, 0x12, 0x59, 0x0a, 0x10, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x5f, 0x70, - 0x75, 0x62, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, - 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, - 0x79, 0x42, 0x18, 0xca, 0xb4, 0x2d, 0x14, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x63, 0x72, - 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x50, 0x75, 0x62, 0x4b, 0x65, 0x79, 0x52, 0x0f, 0x63, 0x6f, 0x6e, - 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x50, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x12, 0x16, 0x0a, 0x06, - 0x6a, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x6a, 0x61, - 0x69, 0x6c, 0x65, 0x64, 0x12, 0x3a, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x0e, 0x32, 0x22, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x73, 0x74, - 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x42, 0x6f, - 0x6e, 0x64, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, - 0x12, 0x43, 0x0a, 0x06, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, - 0x42, 0x2b, 0xc8, 0xde, 0x1f, 0x00, 0xda, 0xde, 0x1f, 0x15, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, - 0x73, 0x64, 0x6b, 0x2e, 0x69, 0x6f, 0x2f, 0x6d, 0x61, 0x74, 0x68, 0x2e, 0x49, 0x6e, 0x74, 0xd2, - 0xb4, 0x2d, 0x0a, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x49, 0x6e, 0x74, 0x52, 0x06, 0x74, - 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x12, 0x5c, 0x0a, 0x10, 0x64, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, - 0x6f, 0x72, 0x5f, 0x73, 0x68, 0x61, 0x72, 0x65, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x42, - 0x31, 0xc8, 0xde, 0x1f, 0x00, 0xda, 0xde, 0x1f, 0x1b, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x73, - 0x64, 0x6b, 0x2e, 0x69, 0x6f, 0x2f, 0x6d, 0x61, 0x74, 0x68, 0x2e, 0x4c, 0x65, 0x67, 0x61, 0x63, - 0x79, 0x44, 0x65, 0x63, 0xd2, 0xb4, 0x2d, 0x0a, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x44, - 0x65, 0x63, 0x52, 0x0f, 0x64, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, 0x53, 0x68, 0x61, - 0x72, 0x65, 0x73, 0x12, 0x50, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, - 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, - 0x73, 0x2e, 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, - 0x31, 0x2e, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x09, 0xc8, - 0xde, 0x1f, 0x00, 0xa8, 0xe7, 0xb0, 0x2a, 0x01, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, - 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x29, 0x0a, 0x10, 0x75, 0x6e, 0x62, 0x6f, 0x6e, 0x64, 0x69, - 0x6e, 0x67, 0x5f, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x03, 0x52, - 0x0f, 0x75, 0x6e, 0x62, 0x6f, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, - 0x12, 0x50, 0x0a, 0x0e, 0x75, 0x6e, 0x62, 0x6f, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x74, 0x69, - 0x6d, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, - 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, - 0x74, 0x61, 0x6d, 0x70, 0x42, 0x0d, 0xc8, 0xde, 0x1f, 0x00, 0x90, 0xdf, 0x1f, 0x01, 0xa8, 0xe7, - 0xb0, 0x2a, 0x01, 0x52, 0x0d, 0x75, 0x6e, 0x62, 0x6f, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x54, 0x69, - 0x6d, 0x65, 0x12, 0x4d, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, - 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, - 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, - 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x42, 0x09, 0xc8, 0xde, 0x1f, 0x00, - 0xa8, 0xe7, 0xb0, 0x2a, 0x01, 0x52, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, - 0x6e, 0x12, 0x6e, 0x0a, 0x13, 0x6d, 0x69, 0x6e, 0x5f, 0x73, 0x65, 0x6c, 0x66, 0x5f, 0x64, 0x65, - 0x6c, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x42, 0x3e, - 0xc8, 0xde, 0x1f, 0x00, 0xda, 0xde, 0x1f, 0x15, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x73, 0x64, - 0x6b, 0x2e, 0x69, 0x6f, 0x2f, 0x6d, 0x61, 0x74, 0x68, 0x2e, 0x49, 0x6e, 0x74, 0xd2, 0xb4, 0x2d, - 0x0a, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x49, 0x6e, 0x74, 0xda, 0xb4, 0x2d, 0x0f, 0x63, - 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2d, 0x73, 0x64, 0x6b, 0x20, 0x30, 0x2e, 0x34, 0x37, 0x52, 0x11, - 0x6d, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x66, 0x44, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x12, 0x3c, 0x0a, 0x1b, 0x75, 0x6e, 0x62, 0x6f, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x6f, - 0x6e, 0x5f, 0x68, 0x6f, 0x6c, 0x64, 0x5f, 0x72, 0x65, 0x66, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, - 0x18, 0x0c, 0x20, 0x01, 0x28, 0x03, 0x52, 0x17, 0x75, 0x6e, 0x62, 0x6f, 0x6e, 0x64, 0x69, 0x6e, - 0x67, 0x4f, 0x6e, 0x48, 0x6f, 0x6c, 0x64, 0x52, 0x65, 0x66, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, - 0x23, 0x0a, 0x0d, 0x75, 0x6e, 0x62, 0x6f, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x69, 0x64, 0x73, - 0x18, 0x0d, 0x20, 0x03, 0x28, 0x04, 0x52, 0x0c, 0x75, 0x6e, 0x62, 0x6f, 0x6e, 0x64, 0x69, 0x6e, - 0x67, 0x49, 0x64, 0x73, 0x3a, 0x08, 0x88, 0xa0, 0x1f, 0x00, 0xe8, 0xa0, 0x1f, 0x00, 0x22, 0x46, - 0x0a, 0x0c, 0x56, 0x61, 0x6c, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x12, 0x36, - 0x0a, 0x09, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, - 0x09, 0x42, 0x18, 0xd2, 0xb4, 0x2d, 0x14, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x64, - 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x09, 0x61, 0x64, 0x64, - 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x22, 0xa9, 0x01, 0x0a, 0x06, 0x44, 0x56, 0x50, 0x61, 0x69, - 0x72, 0x12, 0x45, 0x0a, 0x11, 0x64, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x61, - 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xd2, 0xb4, - 0x2d, 0x14, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, - 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x10, 0x64, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x6f, - 0x72, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x4e, 0x0a, 0x11, 0x76, 0x61, 0x6c, 0x69, - 0x64, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x42, 0x21, 0xd2, 0xb4, 0x2d, 0x1d, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, - 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, - 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x10, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, - 0x72, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x3a, 0x08, 0x88, 0xa0, 0x1f, 0x00, 0xe8, 0xa0, - 0x1f, 0x00, 0x22, 0x4a, 0x0a, 0x07, 0x44, 0x56, 0x50, 0x61, 0x69, 0x72, 0x73, 0x12, 0x3f, 0x0a, - 0x05, 0x70, 0x61, 0x69, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x63, - 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x31, - 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x44, 0x56, 0x50, 0x61, 0x69, 0x72, 0x42, 0x09, 0xc8, 0xde, - 0x1f, 0x00, 0xa8, 0xe7, 0xb0, 0x2a, 0x01, 0x52, 0x05, 0x70, 0x61, 0x69, 0x72, 0x73, 0x22, 0x8b, - 0x02, 0x0a, 0x0a, 0x44, 0x56, 0x56, 0x54, 0x72, 0x69, 0x70, 0x6c, 0x65, 0x74, 0x12, 0x45, 0x0a, - 0x11, 0x64, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, - 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xd2, 0xb4, 0x2d, 0x14, 0x63, 0x6f, - 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, 0x69, - 0x6e, 0x67, 0x52, 0x10, 0x64, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, 0x41, 0x64, 0x64, - 0x72, 0x65, 0x73, 0x73, 0x12, 0x55, 0x0a, 0x15, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, - 0x72, 0x5f, 0x73, 0x72, 0x63, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x42, 0x21, 0xd2, 0xb4, 0x2d, 0x1d, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, - 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, - 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x13, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, - 0x72, 0x53, 0x72, 0x63, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x55, 0x0a, 0x15, 0x76, - 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x64, 0x73, 0x74, 0x5f, 0x61, 0x64, 0x64, - 0x72, 0x65, 0x73, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x21, 0xd2, 0xb4, 0x2d, 0x1d, - 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, - 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x13, 0x76, - 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x44, 0x73, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, - 0x73, 0x73, 0x3a, 0x08, 0x88, 0xa0, 0x1f, 0x00, 0xe8, 0xa0, 0x1f, 0x00, 0x22, 0x58, 0x0a, 0x0b, - 0x44, 0x56, 0x56, 0x54, 0x72, 0x69, 0x70, 0x6c, 0x65, 0x74, 0x73, 0x12, 0x49, 0x0a, 0x08, 0x74, - 0x72, 0x69, 0x70, 0x6c, 0x65, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, - 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x76, - 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x44, 0x56, 0x56, 0x54, 0x72, 0x69, 0x70, 0x6c, 0x65, - 0x74, 0x42, 0x09, 0xc8, 0xde, 0x1f, 0x00, 0xa8, 0xe7, 0xb0, 0x2a, 0x01, 0x52, 0x08, 0x74, 0x72, - 0x69, 0x70, 0x6c, 0x65, 0x74, 0x73, 0x22, 0xf8, 0x01, 0x0a, 0x0a, 0x44, 0x65, 0x6c, 0x65, 0x67, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x45, 0x0a, 0x11, 0x64, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, - 0x6f, 0x72, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x42, 0x18, 0xd2, 0xb4, 0x2d, 0x14, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x64, 0x64, - 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x10, 0x64, 0x65, 0x6c, 0x65, - 0x67, 0x61, 0x74, 0x6f, 0x72, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x4e, 0x0a, 0x11, - 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, - 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x21, 0xd2, 0xb4, 0x2d, 0x1d, 0x63, 0x6f, 0x73, - 0x6d, 0x6f, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x41, 0x64, 0x64, - 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x10, 0x76, 0x61, 0x6c, 0x69, - 0x64, 0x61, 0x74, 0x6f, 0x72, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x49, 0x0a, 0x06, - 0x73, 0x68, 0x61, 0x72, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x31, 0xc8, 0xde, - 0x1f, 0x00, 0xda, 0xde, 0x1f, 0x1b, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x73, 0x64, 0x6b, 0x2e, - 0x69, 0x6f, 0x2f, 0x6d, 0x61, 0x74, 0x68, 0x2e, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x44, 0x65, - 0x63, 0xd2, 0xb4, 0x2d, 0x0a, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x44, 0x65, 0x63, 0x52, - 0x06, 0x73, 0x68, 0x61, 0x72, 0x65, 0x73, 0x3a, 0x08, 0x88, 0xa0, 0x1f, 0x00, 0xe8, 0xa0, 0x1f, - 0x00, 0x22, 0x8d, 0x02, 0x0a, 0x13, 0x55, 0x6e, 0x62, 0x6f, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x44, - 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x45, 0x0a, 0x11, 0x64, 0x65, 0x6c, - 0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xd2, 0xb4, 0x2d, 0x14, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, - 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x10, - 0x64, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, - 0x12, 0x4e, 0x0a, 0x11, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x61, 0x64, - 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x21, 0xd2, 0xb4, 0x2d, - 0x1d, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, - 0x72, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x10, - 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, - 0x12, 0x55, 0x0a, 0x07, 0x65, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x30, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x73, 0x74, 0x61, 0x6b, 0x69, - 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x55, 0x6e, 0x62, 0x6f, 0x6e, - 0x64, 0x69, 0x6e, 0x67, 0x44, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6e, - 0x74, 0x72, 0x79, 0x42, 0x09, 0xc8, 0xde, 0x1f, 0x00, 0xa8, 0xe7, 0xb0, 0x2a, 0x01, 0x52, 0x07, - 0x65, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x3a, 0x08, 0x88, 0xa0, 0x1f, 0x00, 0xe8, 0xa0, 0x1f, - 0x00, 0x22, 0x9b, 0x03, 0x0a, 0x18, 0x55, 0x6e, 0x62, 0x6f, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x44, - 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x27, - 0x0a, 0x0f, 0x63, 0x72, 0x65, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x68, 0x65, 0x69, 0x67, 0x68, - 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x63, 0x72, 0x65, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x52, 0x0a, 0x0f, 0x63, 0x6f, 0x6d, 0x70, 0x6c, - 0x65, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x42, 0x0d, 0xc8, 0xde, - 0x1f, 0x00, 0x90, 0xdf, 0x1f, 0x01, 0xa8, 0xe7, 0xb0, 0x2a, 0x01, 0x52, 0x0e, 0x63, 0x6f, 0x6d, - 0x70, 0x6c, 0x65, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x54, 0x0a, 0x0f, 0x69, - 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x5f, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x09, 0x42, 0x2b, 0xc8, 0xde, 0x1f, 0x00, 0xda, 0xde, 0x1f, 0x15, 0x63, 0x6f, - 0x73, 0x6d, 0x6f, 0x73, 0x73, 0x64, 0x6b, 0x2e, 0x69, 0x6f, 0x2f, 0x6d, 0x61, 0x74, 0x68, 0x2e, - 0x49, 0x6e, 0x74, 0xd2, 0xb4, 0x2d, 0x0a, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x49, 0x6e, - 0x74, 0x52, 0x0e, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, - 0x65, 0x12, 0x45, 0x0a, 0x07, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x04, 0x20, 0x01, - 0x28, 0x09, 0x42, 0x2b, 0xc8, 0xde, 0x1f, 0x00, 0xda, 0xde, 0x1f, 0x15, 0x63, 0x6f, 0x73, 0x6d, - 0x6f, 0x73, 0x73, 0x64, 0x6b, 0x2e, 0x69, 0x6f, 0x2f, 0x6d, 0x61, 0x74, 0x68, 0x2e, 0x49, 0x6e, - 0x74, 0xd2, 0xb4, 0x2d, 0x0a, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x49, 0x6e, 0x74, 0x52, - 0x07, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x75, 0x6e, 0x62, 0x6f, - 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, - 0x75, 0x6e, 0x62, 0x6f, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x49, 0x64, 0x12, 0x3c, 0x0a, 0x1b, 0x75, - 0x6e, 0x62, 0x6f, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x6f, 0x6e, 0x5f, 0x68, 0x6f, 0x6c, 0x64, - 0x5f, 0x72, 0x65, 0x66, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, - 0x52, 0x17, 0x75, 0x6e, 0x62, 0x6f, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x4f, 0x6e, 0x48, 0x6f, 0x6c, - 0x64, 0x52, 0x65, 0x66, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x3a, 0x04, 0xe8, 0xa0, 0x1f, 0x01, 0x22, - 0x9f, 0x03, 0x0a, 0x11, 0x52, 0x65, 0x64, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x27, 0x0a, 0x0f, 0x63, 0x72, 0x65, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x5f, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, - 0x63, 0x72, 0x65, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x52, - 0x0a, 0x0f, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x69, 0x6d, - 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, - 0x61, 0x6d, 0x70, 0x42, 0x0d, 0xc8, 0xde, 0x1f, 0x00, 0x90, 0xdf, 0x1f, 0x01, 0xa8, 0xe7, 0xb0, - 0x2a, 0x01, 0x52, 0x0e, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x69, - 0x6d, 0x65, 0x12, 0x54, 0x0a, 0x0f, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x5f, 0x62, 0x61, - 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x2b, 0xc8, 0xde, 0x1f, - 0x00, 0xda, 0xde, 0x1f, 0x15, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x73, 0x64, 0x6b, 0x2e, 0x69, - 0x6f, 0x2f, 0x6d, 0x61, 0x74, 0x68, 0x2e, 0x49, 0x6e, 0x74, 0xd2, 0xb4, 0x2d, 0x0a, 0x63, 0x6f, - 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x49, 0x6e, 0x74, 0x52, 0x0e, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, - 0x6c, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x50, 0x0a, 0x0a, 0x73, 0x68, 0x61, 0x72, - 0x65, 0x73, 0x5f, 0x64, 0x73, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x42, 0x31, 0xc8, 0xde, - 0x1f, 0x00, 0xda, 0xde, 0x1f, 0x1b, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x73, 0x64, 0x6b, 0x2e, - 0x69, 0x6f, 0x2f, 0x6d, 0x61, 0x74, 0x68, 0x2e, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x44, 0x65, - 0x63, 0xd2, 0xb4, 0x2d, 0x0a, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x44, 0x65, 0x63, 0x52, - 0x09, 0x73, 0x68, 0x61, 0x72, 0x65, 0x73, 0x44, 0x73, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x75, 0x6e, - 0x62, 0x6f, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, - 0x52, 0x0b, 0x75, 0x6e, 0x62, 0x6f, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x49, 0x64, 0x12, 0x3c, 0x0a, - 0x1b, 0x75, 0x6e, 0x62, 0x6f, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x6f, 0x6e, 0x5f, 0x68, 0x6f, - 0x6c, 0x64, 0x5f, 0x72, 0x65, 0x66, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x06, 0x20, 0x01, - 0x28, 0x03, 0x52, 0x17, 0x75, 0x6e, 0x62, 0x6f, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x4f, 0x6e, 0x48, - 0x6f, 0x6c, 0x64, 0x52, 0x65, 0x66, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x3a, 0x04, 0xe8, 0xa0, 0x1f, - 0x01, 0x22, 0xdd, 0x02, 0x0a, 0x0c, 0x52, 0x65, 0x64, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x12, 0x45, 0x0a, 0x11, 0x64, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, 0x5f, + 0x07, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x12, 0x47, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, + 0x64, 0x61, 0x74, 0x61, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x63, 0x6f, 0x73, + 0x6d, 0x6f, 0x73, 0x2e, 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x62, 0x65, + 0x74, 0x61, 0x31, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x42, 0x09, 0xc8, 0xde, + 0x1f, 0x00, 0xa8, 0xe7, 0xb0, 0x2a, 0x01, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, + 0x61, 0x3a, 0x04, 0xe8, 0xa0, 0x1f, 0x01, 0x22, 0x66, 0x0a, 0x08, 0x4d, 0x65, 0x74, 0x61, 0x64, + 0x61, 0x74, 0x61, 0x12, 0x26, 0x0a, 0x0f, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x70, + 0x69, 0x63, 0x5f, 0x75, 0x72, 0x69, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x70, 0x72, + 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x50, 0x69, 0x63, 0x55, 0x72, 0x69, 0x12, 0x2c, 0x0a, 0x12, 0x73, + 0x6f, 0x63, 0x69, 0x61, 0x6c, 0x5f, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x5f, 0x75, 0x72, 0x69, + 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x10, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x6c, 0x48, + 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x55, 0x72, 0x69, 0x73, 0x3a, 0x04, 0xe8, 0xa0, 0x1f, 0x01, 0x22, + 0x9d, 0x07, 0x0a, 0x09, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x12, 0x43, 0x0a, + 0x10, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, + 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xd2, 0xb4, 0x2d, 0x14, 0x63, 0x6f, 0x73, + 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, + 0x67, 0x52, 0x0f, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x41, 0x64, 0x64, 0x72, 0x65, + 0x73, 0x73, 0x12, 0x59, 0x0a, 0x10, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x5f, + 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, + 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, + 0x6e, 0x79, 0x42, 0x18, 0xca, 0xb4, 0x2d, 0x14, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x63, + 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x50, 0x75, 0x62, 0x4b, 0x65, 0x79, 0x52, 0x0f, 0x63, 0x6f, + 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x50, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x12, 0x16, 0x0a, + 0x06, 0x6a, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x6a, + 0x61, 0x69, 0x6c, 0x65, 0x64, 0x12, 0x3a, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x22, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x73, + 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x42, + 0x6f, 0x6e, 0x64, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x12, 0x43, 0x0a, 0x06, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, + 0x09, 0x42, 0x2b, 0xc8, 0xde, 0x1f, 0x00, 0xda, 0xde, 0x1f, 0x15, 0x63, 0x6f, 0x73, 0x6d, 0x6f, + 0x73, 0x73, 0x64, 0x6b, 0x2e, 0x69, 0x6f, 0x2f, 0x6d, 0x61, 0x74, 0x68, 0x2e, 0x49, 0x6e, 0x74, + 0xd2, 0xb4, 0x2d, 0x0a, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x49, 0x6e, 0x74, 0x52, 0x06, + 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x12, 0x5c, 0x0a, 0x10, 0x64, 0x65, 0x6c, 0x65, 0x67, 0x61, + 0x74, 0x6f, 0x72, 0x5f, 0x73, 0x68, 0x61, 0x72, 0x65, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, + 0x42, 0x31, 0xc8, 0xde, 0x1f, 0x00, 0xda, 0xde, 0x1f, 0x1b, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, + 0x73, 0x64, 0x6b, 0x2e, 0x69, 0x6f, 0x2f, 0x6d, 0x61, 0x74, 0x68, 0x2e, 0x4c, 0x65, 0x67, 0x61, + 0x63, 0x79, 0x44, 0x65, 0x63, 0xd2, 0xb4, 0x2d, 0x0a, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, + 0x44, 0x65, 0x63, 0x52, 0x0f, 0x64, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, 0x53, 0x68, + 0x61, 0x72, 0x65, 0x73, 0x12, 0x50, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, + 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x63, 0x6f, 0x73, 0x6d, + 0x6f, 0x73, 0x2e, 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, + 0x61, 0x31, 0x2e, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x09, + 0xc8, 0xde, 0x1f, 0x00, 0xa8, 0xe7, 0xb0, 0x2a, 0x01, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, + 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x29, 0x0a, 0x10, 0x75, 0x6e, 0x62, 0x6f, 0x6e, 0x64, + 0x69, 0x6e, 0x67, 0x5f, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x03, + 0x52, 0x0f, 0x75, 0x6e, 0x62, 0x6f, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x48, 0x65, 0x69, 0x67, 0x68, + 0x74, 0x12, 0x50, 0x0a, 0x0e, 0x75, 0x6e, 0x62, 0x6f, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x74, + 0x69, 0x6d, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, + 0x73, 0x74, 0x61, 0x6d, 0x70, 0x42, 0x0d, 0xc8, 0xde, 0x1f, 0x00, 0x90, 0xdf, 0x1f, 0x01, 0xa8, + 0xe7, 0xb0, 0x2a, 0x01, 0x52, 0x0d, 0x75, 0x6e, 0x62, 0x6f, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x54, + 0x69, 0x6d, 0x65, 0x12, 0x4d, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, + 0x6e, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, + 0x2e, 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, + 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x42, 0x09, 0xc8, 0xde, 0x1f, + 0x00, 0xa8, 0xe7, 0xb0, 0x2a, 0x01, 0x52, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x73, 0x73, 0x69, + 0x6f, 0x6e, 0x12, 0x6e, 0x0a, 0x13, 0x6d, 0x69, 0x6e, 0x5f, 0x73, 0x65, 0x6c, 0x66, 0x5f, 0x64, + 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x42, + 0x3e, 0xc8, 0xde, 0x1f, 0x00, 0xda, 0xde, 0x1f, 0x15, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x73, + 0x64, 0x6b, 0x2e, 0x69, 0x6f, 0x2f, 0x6d, 0x61, 0x74, 0x68, 0x2e, 0x49, 0x6e, 0x74, 0xd2, 0xb4, + 0x2d, 0x0a, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x49, 0x6e, 0x74, 0xda, 0xb4, 0x2d, 0x0f, + 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2d, 0x73, 0x64, 0x6b, 0x20, 0x30, 0x2e, 0x34, 0x37, 0x52, + 0x11, 0x6d, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x66, 0x44, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x12, 0x3c, 0x0a, 0x1b, 0x75, 0x6e, 0x62, 0x6f, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f, + 0x6f, 0x6e, 0x5f, 0x68, 0x6f, 0x6c, 0x64, 0x5f, 0x72, 0x65, 0x66, 0x5f, 0x63, 0x6f, 0x75, 0x6e, + 0x74, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x03, 0x52, 0x17, 0x75, 0x6e, 0x62, 0x6f, 0x6e, 0x64, 0x69, + 0x6e, 0x67, 0x4f, 0x6e, 0x48, 0x6f, 0x6c, 0x64, 0x52, 0x65, 0x66, 0x43, 0x6f, 0x75, 0x6e, 0x74, + 0x12, 0x23, 0x0a, 0x0d, 0x75, 0x6e, 0x62, 0x6f, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x69, 0x64, + 0x73, 0x18, 0x0d, 0x20, 0x03, 0x28, 0x04, 0x52, 0x0c, 0x75, 0x6e, 0x62, 0x6f, 0x6e, 0x64, 0x69, + 0x6e, 0x67, 0x49, 0x64, 0x73, 0x3a, 0x08, 0x88, 0xa0, 0x1f, 0x00, 0xe8, 0xa0, 0x1f, 0x00, 0x22, + 0x46, 0x0a, 0x0c, 0x56, 0x61, 0x6c, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x12, + 0x36, 0x0a, 0x09, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, + 0x28, 0x09, 0x42, 0x18, 0xd2, 0xb4, 0x2d, 0x14, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x41, + 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x09, 0x61, 0x64, + 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x22, 0xa9, 0x01, 0x0a, 0x06, 0x44, 0x56, 0x50, 0x61, + 0x69, 0x72, 0x12, 0x45, 0x0a, 0x11, 0x64, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xd2, 0xb4, 0x2d, 0x14, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x10, 0x64, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, - 0x6f, 0x72, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x55, 0x0a, 0x15, 0x76, 0x61, 0x6c, - 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x73, 0x72, 0x63, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, + 0x6f, 0x72, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x4e, 0x0a, 0x11, 0x76, 0x61, 0x6c, + 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x42, 0x21, 0xd2, 0xb4, 0x2d, 0x1d, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, + 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, + 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x10, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, + 0x6f, 0x72, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x3a, 0x08, 0x88, 0xa0, 0x1f, 0x00, 0xe8, + 0xa0, 0x1f, 0x00, 0x22, 0x4a, 0x0a, 0x07, 0x44, 0x56, 0x50, 0x61, 0x69, 0x72, 0x73, 0x12, 0x3f, + 0x0a, 0x05, 0x70, 0x61, 0x69, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, + 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x76, + 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x44, 0x56, 0x50, 0x61, 0x69, 0x72, 0x42, 0x09, 0xc8, + 0xde, 0x1f, 0x00, 0xa8, 0xe7, 0xb0, 0x2a, 0x01, 0x52, 0x05, 0x70, 0x61, 0x69, 0x72, 0x73, 0x22, + 0x8b, 0x02, 0x0a, 0x0a, 0x44, 0x56, 0x56, 0x54, 0x72, 0x69, 0x70, 0x6c, 0x65, 0x74, 0x12, 0x45, + 0x0a, 0x11, 0x64, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x61, 0x64, 0x64, 0x72, + 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xd2, 0xb4, 0x2d, 0x14, 0x63, + 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, + 0x69, 0x6e, 0x67, 0x52, 0x10, 0x64, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, 0x41, 0x64, + 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x55, 0x0a, 0x15, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, + 0x6f, 0x72, 0x5f, 0x73, 0x72, 0x63, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x42, 0x21, 0xd2, 0xb4, 0x2d, 0x1d, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, + 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, + 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x13, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, + 0x6f, 0x72, 0x53, 0x72, 0x63, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x55, 0x0a, 0x15, + 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x64, 0x73, 0x74, 0x5f, 0x61, 0x64, + 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x21, 0xd2, 0xb4, 0x2d, + 0x1d, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, + 0x72, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x13, + 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x44, 0x73, 0x74, 0x41, 0x64, 0x64, 0x72, + 0x65, 0x73, 0x73, 0x3a, 0x08, 0x88, 0xa0, 0x1f, 0x00, 0xe8, 0xa0, 0x1f, 0x00, 0x22, 0x58, 0x0a, + 0x0b, 0x44, 0x56, 0x56, 0x54, 0x72, 0x69, 0x70, 0x6c, 0x65, 0x74, 0x73, 0x12, 0x49, 0x0a, 0x08, + 0x74, 0x72, 0x69, 0x70, 0x6c, 0x65, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, + 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2e, + 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x44, 0x56, 0x56, 0x54, 0x72, 0x69, 0x70, 0x6c, + 0x65, 0x74, 0x42, 0x09, 0xc8, 0xde, 0x1f, 0x00, 0xa8, 0xe7, 0xb0, 0x2a, 0x01, 0x52, 0x08, 0x74, + 0x72, 0x69, 0x70, 0x6c, 0x65, 0x74, 0x73, 0x22, 0xf8, 0x01, 0x0a, 0x0a, 0x44, 0x65, 0x6c, 0x65, + 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x45, 0x0a, 0x11, 0x64, 0x65, 0x6c, 0x65, 0x67, 0x61, + 0x74, 0x6f, 0x72, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x42, 0x18, 0xd2, 0xb4, 0x2d, 0x14, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x64, + 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x10, 0x64, 0x65, 0x6c, + 0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x4e, 0x0a, + 0x11, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x21, 0xd2, 0xb4, 0x2d, 0x1d, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x41, 0x64, - 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x13, 0x76, 0x61, 0x6c, - 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x53, 0x72, 0x63, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, - 0x12, 0x55, 0x0a, 0x15, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x64, 0x73, - 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, - 0x21, 0xd2, 0xb4, 0x2d, 0x1d, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x69, - 0x64, 0x61, 0x74, 0x6f, 0x72, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, 0x69, - 0x6e, 0x67, 0x52, 0x13, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x44, 0x73, 0x74, - 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x4e, 0x0a, 0x07, 0x65, 0x6e, 0x74, 0x72, 0x69, - 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, - 0x73, 0x2e, 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, - 0x31, 0x2e, 0x52, 0x65, 0x64, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6e, - 0x74, 0x72, 0x79, 0x42, 0x09, 0xc8, 0xde, 0x1f, 0x00, 0xa8, 0xe7, 0xb0, 0x2a, 0x01, 0x52, 0x07, - 0x65, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x3a, 0x08, 0x88, 0xa0, 0x1f, 0x00, 0xe8, 0xa0, 0x1f, - 0x00, 0x22, 0xeb, 0x03, 0x0a, 0x06, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x4f, 0x0a, 0x0e, - 0x75, 0x6e, 0x62, 0x6f, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, - 0x0d, 0xc8, 0xde, 0x1f, 0x00, 0x98, 0xdf, 0x1f, 0x01, 0xa8, 0xe7, 0xb0, 0x2a, 0x01, 0x52, 0x0d, - 0x75, 0x6e, 0x62, 0x6f, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x25, 0x0a, - 0x0e, 0x6d, 0x61, 0x78, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0d, 0x6d, 0x61, 0x78, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, - 0x74, 0x6f, 0x72, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x6d, 0x61, 0x78, 0x5f, 0x65, 0x6e, 0x74, 0x72, - 0x69, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x6d, 0x61, 0x78, 0x45, 0x6e, - 0x74, 0x72, 0x69, 0x65, 0x73, 0x12, 0x31, 0x0a, 0x12, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x69, - 0x63, 0x61, 0x6c, 0x5f, 0x65, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, - 0x0d, 0x42, 0x02, 0x18, 0x01, 0x52, 0x11, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x69, 0x63, 0x61, - 0x6c, 0x45, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x62, 0x6f, 0x6e, 0x64, - 0x5f, 0x64, 0x65, 0x6e, 0x6f, 0x6d, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x62, 0x6f, - 0x6e, 0x64, 0x44, 0x65, 0x6e, 0x6f, 0x6d, 0x12, 0x84, 0x01, 0x0a, 0x13, 0x6d, 0x69, 0x6e, 0x5f, - 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x72, 0x61, 0x74, 0x65, 0x18, - 0x06, 0x20, 0x01, 0x28, 0x09, 0x42, 0x54, 0xc8, 0xde, 0x1f, 0x00, 0xda, 0xde, 0x1f, 0x1b, 0x63, + 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x10, 0x76, 0x61, 0x6c, + 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x49, 0x0a, + 0x06, 0x73, 0x68, 0x61, 0x72, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x31, 0xc8, + 0xde, 0x1f, 0x00, 0xda, 0xde, 0x1f, 0x1b, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x73, 0x64, 0x6b, + 0x2e, 0x69, 0x6f, 0x2f, 0x6d, 0x61, 0x74, 0x68, 0x2e, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x44, + 0x65, 0x63, 0xd2, 0xb4, 0x2d, 0x0a, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x44, 0x65, 0x63, + 0x52, 0x06, 0x73, 0x68, 0x61, 0x72, 0x65, 0x73, 0x3a, 0x08, 0x88, 0xa0, 0x1f, 0x00, 0xe8, 0xa0, + 0x1f, 0x00, 0x22, 0x8d, 0x02, 0x0a, 0x13, 0x55, 0x6e, 0x62, 0x6f, 0x6e, 0x64, 0x69, 0x6e, 0x67, + 0x44, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x45, 0x0a, 0x11, 0x64, 0x65, + 0x6c, 0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xd2, 0xb4, 0x2d, 0x14, 0x63, 0x6f, 0x73, 0x6d, 0x6f, + 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, + 0x10, 0x64, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, + 0x73, 0x12, 0x4e, 0x0a, 0x11, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x61, + 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x21, 0xd2, 0xb4, + 0x2d, 0x1d, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, + 0x6f, 0x72, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, + 0x10, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, + 0x73, 0x12, 0x55, 0x0a, 0x07, 0x65, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x73, 0x74, 0x61, 0x6b, + 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x55, 0x6e, 0x62, 0x6f, + 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x44, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, + 0x6e, 0x74, 0x72, 0x79, 0x42, 0x09, 0xc8, 0xde, 0x1f, 0x00, 0xa8, 0xe7, 0xb0, 0x2a, 0x01, 0x52, + 0x07, 0x65, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x3a, 0x08, 0x88, 0xa0, 0x1f, 0x00, 0xe8, 0xa0, + 0x1f, 0x00, 0x22, 0x9b, 0x03, 0x0a, 0x18, 0x55, 0x6e, 0x62, 0x6f, 0x6e, 0x64, 0x69, 0x6e, 0x67, + 0x44, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, + 0x27, 0x0a, 0x0f, 0x63, 0x72, 0x65, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x68, 0x65, 0x69, 0x67, + 0x68, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x63, 0x72, 0x65, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x52, 0x0a, 0x0f, 0x63, 0x6f, 0x6d, 0x70, + 0x6c, 0x65, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x42, 0x0d, 0xc8, + 0xde, 0x1f, 0x00, 0x90, 0xdf, 0x1f, 0x01, 0xa8, 0xe7, 0xb0, 0x2a, 0x01, 0x52, 0x0e, 0x63, 0x6f, + 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x54, 0x0a, 0x0f, + 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x5f, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x2b, 0xc8, 0xde, 0x1f, 0x00, 0xda, 0xde, 0x1f, 0x15, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x73, 0x64, 0x6b, 0x2e, 0x69, 0x6f, 0x2f, 0x6d, 0x61, 0x74, 0x68, - 0x2e, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x44, 0x65, 0x63, 0xf2, 0xde, 0x1f, 0x1a, 0x79, 0x61, - 0x6d, 0x6c, 0x3a, 0x22, 0x6d, 0x69, 0x6e, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x73, 0x73, 0x69, - 0x6f, 0x6e, 0x5f, 0x72, 0x61, 0x74, 0x65, 0x22, 0xd2, 0xb4, 0x2d, 0x0a, 0x63, 0x6f, 0x73, 0x6d, - 0x6f, 0x73, 0x2e, 0x44, 0x65, 0x63, 0xa8, 0xe7, 0xb0, 0x2a, 0x01, 0x52, 0x11, 0x6d, 0x69, 0x6e, - 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x61, 0x74, 0x65, 0x12, 0x49, - 0x0a, 0x10, 0x6b, 0x65, 0x79, 0x5f, 0x72, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x66, - 0x65, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, - 0x73, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, - 0x6f, 0x69, 0x6e, 0x42, 0x04, 0xc8, 0xde, 0x1f, 0x00, 0x52, 0x0e, 0x6b, 0x65, 0x79, 0x52, 0x6f, - 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x65, 0x65, 0x3a, 0x24, 0xe8, 0xa0, 0x1f, 0x01, 0x8a, - 0xe7, 0xb0, 0x2a, 0x1b, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2d, 0x73, 0x64, 0x6b, 0x2f, 0x78, - 0x2f, 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2f, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x22, - 0xa9, 0x01, 0x0a, 0x12, 0x44, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4d, 0x0a, 0x0a, 0x64, 0x65, 0x6c, 0x65, 0x67, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x63, 0x6f, 0x73, - 0x6d, 0x6f, 0x73, 0x2e, 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x62, 0x65, - 0x74, 0x61, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x09, - 0xc8, 0xde, 0x1f, 0x00, 0xa8, 0xe7, 0xb0, 0x2a, 0x01, 0x52, 0x0a, 0x64, 0x65, 0x6c, 0x65, 0x67, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x3e, 0x0a, 0x07, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, - 0x62, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x69, - 0x6e, 0x42, 0x09, 0xc8, 0xde, 0x1f, 0x00, 0xa8, 0xe7, 0xb0, 0x2a, 0x01, 0x52, 0x07, 0x62, 0x61, - 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x3a, 0x04, 0xe8, 0xa0, 0x1f, 0x00, 0x22, 0xcd, 0x01, 0x0a, 0x19, + 0x2e, 0x49, 0x6e, 0x74, 0xd2, 0xb4, 0x2d, 0x0a, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x49, + 0x6e, 0x74, 0x52, 0x0e, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x42, 0x61, 0x6c, 0x61, 0x6e, + 0x63, 0x65, 0x12, 0x45, 0x0a, 0x07, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x09, 0x42, 0x2b, 0xc8, 0xde, 0x1f, 0x00, 0xda, 0xde, 0x1f, 0x15, 0x63, 0x6f, 0x73, + 0x6d, 0x6f, 0x73, 0x73, 0x64, 0x6b, 0x2e, 0x69, 0x6f, 0x2f, 0x6d, 0x61, 0x74, 0x68, 0x2e, 0x49, + 0x6e, 0x74, 0xd2, 0xb4, 0x2d, 0x0a, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x49, 0x6e, 0x74, + 0x52, 0x07, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x75, 0x6e, 0x62, + 0x6f, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, + 0x0b, 0x75, 0x6e, 0x62, 0x6f, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x49, 0x64, 0x12, 0x3c, 0x0a, 0x1b, + 0x75, 0x6e, 0x62, 0x6f, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x6f, 0x6e, 0x5f, 0x68, 0x6f, 0x6c, + 0x64, 0x5f, 0x72, 0x65, 0x66, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, + 0x03, 0x52, 0x17, 0x75, 0x6e, 0x62, 0x6f, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x4f, 0x6e, 0x48, 0x6f, + 0x6c, 0x64, 0x52, 0x65, 0x66, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x3a, 0x04, 0xe8, 0xa0, 0x1f, 0x01, + 0x22, 0x9f, 0x03, 0x0a, 0x11, 0x52, 0x65, 0x64, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x27, 0x0a, 0x0f, 0x63, 0x72, 0x65, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x5f, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, + 0x0e, 0x63, 0x72, 0x65, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, + 0x52, 0x0a, 0x0f, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x69, + 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, + 0x74, 0x61, 0x6d, 0x70, 0x42, 0x0d, 0xc8, 0xde, 0x1f, 0x00, 0x90, 0xdf, 0x1f, 0x01, 0xa8, 0xe7, + 0xb0, 0x2a, 0x01, 0x52, 0x0e, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x69, 0x6f, 0x6e, 0x54, + 0x69, 0x6d, 0x65, 0x12, 0x54, 0x0a, 0x0f, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x5f, 0x62, + 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x2b, 0xc8, 0xde, + 0x1f, 0x00, 0xda, 0xde, 0x1f, 0x15, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x73, 0x64, 0x6b, 0x2e, + 0x69, 0x6f, 0x2f, 0x6d, 0x61, 0x74, 0x68, 0x2e, 0x49, 0x6e, 0x74, 0xd2, 0xb4, 0x2d, 0x0a, 0x63, + 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x49, 0x6e, 0x74, 0x52, 0x0e, 0x69, 0x6e, 0x69, 0x74, 0x69, + 0x61, 0x6c, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x50, 0x0a, 0x0a, 0x73, 0x68, 0x61, + 0x72, 0x65, 0x73, 0x5f, 0x64, 0x73, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x42, 0x31, 0xc8, + 0xde, 0x1f, 0x00, 0xda, 0xde, 0x1f, 0x1b, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x73, 0x64, 0x6b, + 0x2e, 0x69, 0x6f, 0x2f, 0x6d, 0x61, 0x74, 0x68, 0x2e, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x44, + 0x65, 0x63, 0xd2, 0xb4, 0x2d, 0x0a, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x44, 0x65, 0x63, + 0x52, 0x09, 0x73, 0x68, 0x61, 0x72, 0x65, 0x73, 0x44, 0x73, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x75, + 0x6e, 0x62, 0x6f, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, + 0x04, 0x52, 0x0b, 0x75, 0x6e, 0x62, 0x6f, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x49, 0x64, 0x12, 0x3c, + 0x0a, 0x1b, 0x75, 0x6e, 0x62, 0x6f, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x6f, 0x6e, 0x5f, 0x68, + 0x6f, 0x6c, 0x64, 0x5f, 0x72, 0x65, 0x66, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x06, 0x20, + 0x01, 0x28, 0x03, 0x52, 0x17, 0x75, 0x6e, 0x62, 0x6f, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x4f, 0x6e, + 0x48, 0x6f, 0x6c, 0x64, 0x52, 0x65, 0x66, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x3a, 0x04, 0xe8, 0xa0, + 0x1f, 0x01, 0x22, 0xdd, 0x02, 0x0a, 0x0c, 0x52, 0x65, 0x64, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x12, 0x45, 0x0a, 0x11, 0x64, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, + 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, + 0xd2, 0xb4, 0x2d, 0x14, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, + 0x73, 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x10, 0x64, 0x65, 0x6c, 0x65, 0x67, 0x61, + 0x74, 0x6f, 0x72, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x55, 0x0a, 0x15, 0x76, 0x61, + 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x73, 0x72, 0x63, 0x5f, 0x61, 0x64, 0x64, 0x72, + 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x21, 0xd2, 0xb4, 0x2d, 0x1d, 0x63, + 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x41, + 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x13, 0x76, 0x61, + 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x53, 0x72, 0x63, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, + 0x73, 0x12, 0x55, 0x0a, 0x15, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x64, + 0x73, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, + 0x42, 0x21, 0xd2, 0xb4, 0x2d, 0x1d, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x56, 0x61, 0x6c, + 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, + 0x69, 0x6e, 0x67, 0x52, 0x13, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x44, 0x73, + 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x4e, 0x0a, 0x07, 0x65, 0x6e, 0x74, 0x72, + 0x69, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x63, 0x6f, 0x73, 0x6d, + 0x6f, 0x73, 0x2e, 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, + 0x61, 0x31, 0x2e, 0x52, 0x65, 0x64, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, + 0x6e, 0x74, 0x72, 0x79, 0x42, 0x09, 0xc8, 0xde, 0x1f, 0x00, 0xa8, 0xe7, 0xb0, 0x2a, 0x01, 0x52, + 0x07, 0x65, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x3a, 0x08, 0x88, 0xa0, 0x1f, 0x00, 0xe8, 0xa0, + 0x1f, 0x00, 0x22, 0xeb, 0x03, 0x0a, 0x06, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x4f, 0x0a, + 0x0e, 0x75, 0x6e, 0x62, 0x6f, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x42, 0x0d, 0xc8, 0xde, 0x1f, 0x00, 0x98, 0xdf, 0x1f, 0x01, 0xa8, 0xe7, 0xb0, 0x2a, 0x01, 0x52, + 0x0d, 0x75, 0x6e, 0x62, 0x6f, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x25, + 0x0a, 0x0e, 0x6d, 0x61, 0x78, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0d, 0x6d, 0x61, 0x78, 0x56, 0x61, 0x6c, 0x69, 0x64, + 0x61, 0x74, 0x6f, 0x72, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x6d, 0x61, 0x78, 0x5f, 0x65, 0x6e, 0x74, + 0x72, 0x69, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x6d, 0x61, 0x78, 0x45, + 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x12, 0x31, 0x0a, 0x12, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x72, + 0x69, 0x63, 0x61, 0x6c, 0x5f, 0x65, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x0d, 0x42, 0x02, 0x18, 0x01, 0x52, 0x11, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x69, 0x63, + 0x61, 0x6c, 0x45, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x62, 0x6f, 0x6e, + 0x64, 0x5f, 0x64, 0x65, 0x6e, 0x6f, 0x6d, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x62, + 0x6f, 0x6e, 0x64, 0x44, 0x65, 0x6e, 0x6f, 0x6d, 0x12, 0x84, 0x01, 0x0a, 0x13, 0x6d, 0x69, 0x6e, + 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x72, 0x61, 0x74, 0x65, + 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x42, 0x54, 0xc8, 0xde, 0x1f, 0x00, 0xda, 0xde, 0x1f, 0x1b, + 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x73, 0x64, 0x6b, 0x2e, 0x69, 0x6f, 0x2f, 0x6d, 0x61, 0x74, + 0x68, 0x2e, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x44, 0x65, 0x63, 0xf2, 0xde, 0x1f, 0x1a, 0x79, + 0x61, 0x6d, 0x6c, 0x3a, 0x22, 0x6d, 0x69, 0x6e, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x73, 0x73, + 0x69, 0x6f, 0x6e, 0x5f, 0x72, 0x61, 0x74, 0x65, 0x22, 0xd2, 0xb4, 0x2d, 0x0a, 0x63, 0x6f, 0x73, + 0x6d, 0x6f, 0x73, 0x2e, 0x44, 0x65, 0x63, 0xa8, 0xe7, 0xb0, 0x2a, 0x01, 0x52, 0x11, 0x6d, 0x69, + 0x6e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x61, 0x74, 0x65, 0x12, + 0x49, 0x0a, 0x10, 0x6b, 0x65, 0x79, 0x5f, 0x72, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, + 0x66, 0x65, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x63, 0x6f, 0x73, 0x6d, + 0x6f, 0x73, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, + 0x43, 0x6f, 0x69, 0x6e, 0x42, 0x04, 0xc8, 0xde, 0x1f, 0x00, 0x52, 0x0e, 0x6b, 0x65, 0x79, 0x52, + 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x65, 0x65, 0x3a, 0x24, 0xe8, 0xa0, 0x1f, 0x01, + 0x8a, 0xe7, 0xb0, 0x2a, 0x1b, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2d, 0x73, 0x64, 0x6b, 0x2f, + 0x78, 0x2f, 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2f, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, + 0x22, 0xa9, 0x01, 0x0a, 0x12, 0x44, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4d, 0x0a, 0x0a, 0x64, 0x65, 0x6c, 0x65, 0x67, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x63, 0x6f, + 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x62, + 0x65, 0x74, 0x61, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, + 0x09, 0xc8, 0xde, 0x1f, 0x00, 0xa8, 0xe7, 0xb0, 0x2a, 0x01, 0x52, 0x0a, 0x64, 0x65, 0x6c, 0x65, + 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x3e, 0x0a, 0x07, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, + 0x2e, 0x62, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x6f, + 0x69, 0x6e, 0x42, 0x09, 0xc8, 0xde, 0x1f, 0x00, 0xa8, 0xe7, 0xb0, 0x2a, 0x01, 0x52, 0x07, 0x62, + 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x3a, 0x04, 0xe8, 0xa0, 0x1f, 0x00, 0x22, 0xcd, 0x01, 0x0a, + 0x19, 0x52, 0x65, 0x64, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x74, + 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x63, 0x0a, 0x12, 0x72, 0x65, + 0x64, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x65, 0x6e, 0x74, 0x72, 0x79, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, + 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x52, 0x65, 0x64, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x74, 0x72, - 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x63, 0x0a, 0x12, 0x72, 0x65, 0x64, - 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x73, - 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x52, - 0x65, 0x64, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x74, 0x72, 0x79, - 0x42, 0x09, 0xc8, 0xde, 0x1f, 0x00, 0xa8, 0xe7, 0xb0, 0x2a, 0x01, 0x52, 0x11, 0x72, 0x65, 0x64, - 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x45, - 0x0a, 0x07, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x42, - 0x2b, 0xc8, 0xde, 0x1f, 0x00, 0xda, 0xde, 0x1f, 0x15, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x73, - 0x64, 0x6b, 0x2e, 0x69, 0x6f, 0x2f, 0x6d, 0x61, 0x74, 0x68, 0x2e, 0x49, 0x6e, 0x74, 0xd2, 0xb4, - 0x2d, 0x0a, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x49, 0x6e, 0x74, 0x52, 0x07, 0x62, 0x61, - 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x3a, 0x04, 0xe8, 0xa0, 0x1f, 0x01, 0x22, 0xc9, 0x01, 0x0a, 0x14, - 0x52, 0x65, 0x64, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x53, 0x0a, 0x0c, 0x72, 0x65, 0x64, 0x65, 0x6c, 0x65, 0x67, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x63, 0x6f, 0x73, - 0x6d, 0x6f, 0x73, 0x2e, 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x62, 0x65, - 0x74, 0x61, 0x31, 0x2e, 0x52, 0x65, 0x64, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x42, 0x09, 0xc8, 0xde, 0x1f, 0x00, 0xa8, 0xe7, 0xb0, 0x2a, 0x01, 0x52, 0x0c, 0x72, 0x65, 0x64, - 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x56, 0x0a, 0x07, 0x65, 0x6e, 0x74, - 0x72, 0x69, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x63, 0x6f, 0x73, - 0x6d, 0x6f, 0x73, 0x2e, 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x62, 0x65, - 0x74, 0x61, 0x31, 0x2e, 0x52, 0x65, 0x64, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x09, 0xc8, - 0xde, 0x1f, 0x00, 0xa8, 0xe7, 0xb0, 0x2a, 0x01, 0x52, 0x07, 0x65, 0x6e, 0x74, 0x72, 0x69, 0x65, - 0x73, 0x3a, 0x04, 0xe8, 0xa0, 0x1f, 0x00, 0x22, 0xeb, 0x01, 0x0a, 0x04, 0x50, 0x6f, 0x6f, 0x6c, - 0x12, 0x71, 0x0a, 0x11, 0x6e, 0x6f, 0x74, 0x5f, 0x62, 0x6f, 0x6e, 0x64, 0x65, 0x64, 0x5f, 0x74, - 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x45, 0xc8, 0xde, 0x1f, - 0x00, 0xda, 0xde, 0x1f, 0x15, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x73, 0x64, 0x6b, 0x2e, 0x69, - 0x6f, 0x2f, 0x6d, 0x61, 0x74, 0x68, 0x2e, 0x49, 0x6e, 0x74, 0xea, 0xde, 0x1f, 0x11, 0x6e, 0x6f, - 0x74, 0x5f, 0x62, 0x6f, 0x6e, 0x64, 0x65, 0x64, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0xd2, - 0xb4, 0x2d, 0x0a, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x49, 0x6e, 0x74, 0xa8, 0xe7, 0xb0, - 0x2a, 0x01, 0x52, 0x0f, 0x6e, 0x6f, 0x74, 0x42, 0x6f, 0x6e, 0x64, 0x65, 0x64, 0x54, 0x6f, 0x6b, - 0x65, 0x6e, 0x73, 0x12, 0x66, 0x0a, 0x0d, 0x62, 0x6f, 0x6e, 0x64, 0x65, 0x64, 0x5f, 0x74, 0x6f, - 0x6b, 0x65, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x41, 0xc8, 0xde, 0x1f, 0x00, - 0xda, 0xde, 0x1f, 0x15, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x73, 0x64, 0x6b, 0x2e, 0x69, 0x6f, - 0x2f, 0x6d, 0x61, 0x74, 0x68, 0x2e, 0x49, 0x6e, 0x74, 0xea, 0xde, 0x1f, 0x0d, 0x62, 0x6f, 0x6e, - 0x64, 0x65, 0x64, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0xd2, 0xb4, 0x2d, 0x0a, 0x63, 0x6f, - 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x49, 0x6e, 0x74, 0xa8, 0xe7, 0xb0, 0x2a, 0x01, 0x52, 0x0c, 0x62, - 0x6f, 0x6e, 0x64, 0x65, 0x64, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x3a, 0x08, 0xe8, 0xa0, 0x1f, - 0x01, 0xf0, 0xa0, 0x1f, 0x01, 0x22, 0x5e, 0x0a, 0x10, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, - 0x6f, 0x72, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, 0x12, 0x46, 0x0a, 0x07, 0x75, 0x70, 0x64, - 0x61, 0x74, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x63, 0x6f, 0x6d, - 0x65, 0x74, 0x62, 0x66, 0x74, 0x2e, 0x61, 0x62, 0x63, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x61, - 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x42, 0x09, 0xc8, - 0xde, 0x1f, 0x00, 0xa8, 0xe7, 0xb0, 0x2a, 0x01, 0x52, 0x07, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, - 0x73, 0x3a, 0x02, 0x18, 0x01, 0x22, 0xd0, 0x02, 0x0a, 0x19, 0x43, 0x6f, 0x6e, 0x73, 0x50, 0x75, - 0x62, 0x4b, 0x65, 0x79, 0x52, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x69, 0x73, 0x74, - 0x6f, 0x72, 0x79, 0x12, 0x29, 0x0a, 0x10, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x5f, - 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0f, 0x6f, - 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x56, - 0x0a, 0x0f, 0x6f, 0x6c, 0x64, 0x5f, 0x63, 0x6f, 0x6e, 0x73, 0x5f, 0x70, 0x75, 0x62, 0x6b, 0x65, - 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x42, 0x18, 0xca, - 0xb4, 0x2d, 0x14, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, - 0x2e, 0x50, 0x75, 0x62, 0x4b, 0x65, 0x79, 0x52, 0x0d, 0x6f, 0x6c, 0x64, 0x43, 0x6f, 0x6e, 0x73, - 0x50, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x12, 0x56, 0x0a, 0x0f, 0x6e, 0x65, 0x77, 0x5f, 0x63, 0x6f, - 0x6e, 0x73, 0x5f, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x42, 0x18, 0xca, 0xb4, 0x2d, 0x14, 0x63, 0x6f, 0x73, 0x6d, 0x6f, - 0x73, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x50, 0x75, 0x62, 0x4b, 0x65, 0x79, 0x52, - 0x0d, 0x6e, 0x65, 0x77, 0x43, 0x6f, 0x6e, 0x73, 0x50, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x12, 0x16, - 0x0a, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, - 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x36, 0x0a, 0x03, 0x66, 0x65, 0x65, 0x18, 0x05, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x62, 0x61, 0x73, - 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x69, 0x6e, 0x42, 0x09, - 0xc8, 0xde, 0x1f, 0x00, 0xa8, 0xe7, 0xb0, 0x2a, 0x01, 0x52, 0x03, 0x66, 0x65, 0x65, 0x3a, 0x08, - 0x88, 0xa0, 0x1f, 0x00, 0xe8, 0xa0, 0x1f, 0x00, 0x22, 0x53, 0x0a, 0x19, 0x56, 0x61, 0x6c, 0x41, - 0x64, 0x64, 0x72, 0x73, 0x4f, 0x66, 0x52, 0x6f, 0x74, 0x61, 0x74, 0x65, 0x64, 0x43, 0x6f, 0x6e, - 0x73, 0x4b, 0x65, 0x79, 0x73, 0x12, 0x36, 0x0a, 0x09, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, - 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x42, 0x18, 0xd2, 0xb4, 0x2d, 0x14, 0x63, 0x6f, - 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, 0x69, - 0x6e, 0x67, 0x52, 0x09, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x2a, 0xb6, 0x01, - 0x0a, 0x0a, 0x42, 0x6f, 0x6e, 0x64, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x2c, 0x0a, 0x17, - 0x42, 0x4f, 0x4e, 0x44, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x55, 0x4e, 0x53, 0x50, - 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x1a, 0x0f, 0x8a, 0x9d, 0x20, 0x0b, 0x55, - 0x6e, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x64, 0x12, 0x26, 0x0a, 0x14, 0x42, 0x4f, - 0x4e, 0x44, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x55, 0x4e, 0x42, 0x4f, 0x4e, 0x44, - 0x45, 0x44, 0x10, 0x01, 0x1a, 0x0c, 0x8a, 0x9d, 0x20, 0x08, 0x55, 0x6e, 0x62, 0x6f, 0x6e, 0x64, - 0x65, 0x64, 0x12, 0x28, 0x0a, 0x15, 0x42, 0x4f, 0x4e, 0x44, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, - 0x53, 0x5f, 0x55, 0x4e, 0x42, 0x4f, 0x4e, 0x44, 0x49, 0x4e, 0x47, 0x10, 0x02, 0x1a, 0x0d, 0x8a, - 0x9d, 0x20, 0x09, 0x55, 0x6e, 0x62, 0x6f, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x12, 0x22, 0x0a, 0x12, - 0x42, 0x4f, 0x4e, 0x44, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x42, 0x4f, 0x4e, 0x44, - 0x45, 0x44, 0x10, 0x03, 0x1a, 0x0a, 0x8a, 0x9d, 0x20, 0x06, 0x42, 0x6f, 0x6e, 0x64, 0x65, 0x64, - 0x1a, 0x04, 0x88, 0xa3, 0x1e, 0x00, 0x2a, 0x5d, 0x0a, 0x0a, 0x49, 0x6e, 0x66, 0x72, 0x61, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1a, 0x0a, 0x16, 0x49, 0x4e, 0x46, 0x52, 0x41, 0x43, 0x54, 0x49, - 0x4f, 0x4e, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, - 0x12, 0x1a, 0x0a, 0x16, 0x49, 0x4e, 0x46, 0x52, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x44, - 0x4f, 0x55, 0x42, 0x4c, 0x45, 0x5f, 0x53, 0x49, 0x47, 0x4e, 0x10, 0x01, 0x12, 0x17, 0x0a, 0x13, - 0x49, 0x4e, 0x46, 0x52, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x44, 0x4f, 0x57, 0x4e, 0x54, - 0x49, 0x4d, 0x45, 0x10, 0x02, 0x42, 0xdc, 0x01, 0x0a, 0x1a, 0x63, 0x6f, 0x6d, 0x2e, 0x63, 0x6f, + 0x79, 0x42, 0x09, 0xc8, 0xde, 0x1f, 0x00, 0xa8, 0xe7, 0xb0, 0x2a, 0x01, 0x52, 0x11, 0x72, 0x65, + 0x64, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, + 0x45, 0x0a, 0x07, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, + 0x42, 0x2b, 0xc8, 0xde, 0x1f, 0x00, 0xda, 0xde, 0x1f, 0x15, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, + 0x73, 0x64, 0x6b, 0x2e, 0x69, 0x6f, 0x2f, 0x6d, 0x61, 0x74, 0x68, 0x2e, 0x49, 0x6e, 0x74, 0xd2, + 0xb4, 0x2d, 0x0a, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x49, 0x6e, 0x74, 0x52, 0x07, 0x62, + 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x3a, 0x04, 0xe8, 0xa0, 0x1f, 0x01, 0x22, 0xc9, 0x01, 0x0a, + 0x14, 0x52, 0x65, 0x64, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x53, 0x0a, 0x0c, 0x72, 0x65, 0x64, 0x65, 0x6c, 0x65, 0x67, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x63, 0x6f, + 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x62, + 0x65, 0x74, 0x61, 0x31, 0x2e, 0x52, 0x65, 0x64, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x42, 0x09, 0xc8, 0xde, 0x1f, 0x00, 0xa8, 0xe7, 0xb0, 0x2a, 0x01, 0x52, 0x0c, 0x72, 0x65, + 0x64, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x56, 0x0a, 0x07, 0x65, 0x6e, + 0x74, 0x72, 0x69, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x62, - 0x65, 0x74, 0x61, 0x31, 0x42, 0x0c, 0x53, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f, - 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x36, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x73, 0x64, 0x6b, 0x2e, - 0x69, 0x6f, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x73, 0x74, - 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x3b, 0x73, 0x74, - 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0xa2, 0x02, 0x03, 0x43, - 0x53, 0x58, 0xaa, 0x02, 0x16, 0x43, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x53, 0x74, 0x61, 0x6b, - 0x69, 0x6e, 0x67, 0x2e, 0x56, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0xca, 0x02, 0x16, 0x43, 0x6f, - 0x73, 0x6d, 0x6f, 0x73, 0x5c, 0x53, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x5c, 0x56, 0x31, 0x62, - 0x65, 0x74, 0x61, 0x31, 0xe2, 0x02, 0x22, 0x43, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x5c, 0x53, 0x74, - 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x5c, 0x56, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x5c, 0x47, 0x50, - 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x18, 0x43, 0x6f, 0x73, 0x6d, - 0x6f, 0x73, 0x3a, 0x3a, 0x53, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x3a, 0x3a, 0x56, 0x31, 0x62, - 0x65, 0x74, 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x65, 0x74, 0x61, 0x31, 0x2e, 0x52, 0x65, 0x64, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x09, + 0xc8, 0xde, 0x1f, 0x00, 0xa8, 0xe7, 0xb0, 0x2a, 0x01, 0x52, 0x07, 0x65, 0x6e, 0x74, 0x72, 0x69, + 0x65, 0x73, 0x3a, 0x04, 0xe8, 0xa0, 0x1f, 0x00, 0x22, 0xeb, 0x01, 0x0a, 0x04, 0x50, 0x6f, 0x6f, + 0x6c, 0x12, 0x71, 0x0a, 0x11, 0x6e, 0x6f, 0x74, 0x5f, 0x62, 0x6f, 0x6e, 0x64, 0x65, 0x64, 0x5f, + 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x45, 0xc8, 0xde, + 0x1f, 0x00, 0xda, 0xde, 0x1f, 0x15, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x73, 0x64, 0x6b, 0x2e, + 0x69, 0x6f, 0x2f, 0x6d, 0x61, 0x74, 0x68, 0x2e, 0x49, 0x6e, 0x74, 0xea, 0xde, 0x1f, 0x11, 0x6e, + 0x6f, 0x74, 0x5f, 0x62, 0x6f, 0x6e, 0x64, 0x65, 0x64, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x73, + 0xd2, 0xb4, 0x2d, 0x0a, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x49, 0x6e, 0x74, 0xa8, 0xe7, + 0xb0, 0x2a, 0x01, 0x52, 0x0f, 0x6e, 0x6f, 0x74, 0x42, 0x6f, 0x6e, 0x64, 0x65, 0x64, 0x54, 0x6f, + 0x6b, 0x65, 0x6e, 0x73, 0x12, 0x66, 0x0a, 0x0d, 0x62, 0x6f, 0x6e, 0x64, 0x65, 0x64, 0x5f, 0x74, + 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x41, 0xc8, 0xde, 0x1f, + 0x00, 0xda, 0xde, 0x1f, 0x15, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x73, 0x64, 0x6b, 0x2e, 0x69, + 0x6f, 0x2f, 0x6d, 0x61, 0x74, 0x68, 0x2e, 0x49, 0x6e, 0x74, 0xea, 0xde, 0x1f, 0x0d, 0x62, 0x6f, + 0x6e, 0x64, 0x65, 0x64, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0xd2, 0xb4, 0x2d, 0x0a, 0x63, + 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x49, 0x6e, 0x74, 0xa8, 0xe7, 0xb0, 0x2a, 0x01, 0x52, 0x0c, + 0x62, 0x6f, 0x6e, 0x64, 0x65, 0x64, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x3a, 0x08, 0xe8, 0xa0, + 0x1f, 0x01, 0xf0, 0xa0, 0x1f, 0x01, 0x22, 0x5e, 0x0a, 0x10, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, + 0x74, 0x6f, 0x72, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, 0x12, 0x46, 0x0a, 0x07, 0x75, 0x70, + 0x64, 0x61, 0x74, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x63, 0x6f, + 0x6d, 0x65, 0x74, 0x62, 0x66, 0x74, 0x2e, 0x61, 0x62, 0x63, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x56, + 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x42, 0x09, + 0xc8, 0xde, 0x1f, 0x00, 0xa8, 0xe7, 0xb0, 0x2a, 0x01, 0x52, 0x07, 0x75, 0x70, 0x64, 0x61, 0x74, + 0x65, 0x73, 0x3a, 0x02, 0x18, 0x01, 0x22, 0xd0, 0x02, 0x0a, 0x19, 0x43, 0x6f, 0x6e, 0x73, 0x50, + 0x75, 0x62, 0x4b, 0x65, 0x79, 0x52, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x69, 0x73, + 0x74, 0x6f, 0x72, 0x79, 0x12, 0x29, 0x0a, 0x10, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, + 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0f, + 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, + 0x56, 0x0a, 0x0f, 0x6f, 0x6c, 0x64, 0x5f, 0x63, 0x6f, 0x6e, 0x73, 0x5f, 0x70, 0x75, 0x62, 0x6b, + 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x42, 0x18, + 0xca, 0xb4, 0x2d, 0x14, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, + 0x6f, 0x2e, 0x50, 0x75, 0x62, 0x4b, 0x65, 0x79, 0x52, 0x0d, 0x6f, 0x6c, 0x64, 0x43, 0x6f, 0x6e, + 0x73, 0x50, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x12, 0x56, 0x0a, 0x0f, 0x6e, 0x65, 0x77, 0x5f, 0x63, + 0x6f, 0x6e, 0x73, 0x5f, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x42, 0x18, 0xca, 0xb4, 0x2d, 0x14, 0x63, 0x6f, 0x73, 0x6d, + 0x6f, 0x73, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x2e, 0x50, 0x75, 0x62, 0x4b, 0x65, 0x79, + 0x52, 0x0d, 0x6e, 0x65, 0x77, 0x43, 0x6f, 0x6e, 0x73, 0x50, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x12, + 0x16, 0x0a, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, + 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x36, 0x0a, 0x03, 0x66, 0x65, 0x65, 0x18, 0x05, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x62, 0x61, + 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x69, 0x6e, 0x42, + 0x09, 0xc8, 0xde, 0x1f, 0x00, 0xa8, 0xe7, 0xb0, 0x2a, 0x01, 0x52, 0x03, 0x66, 0x65, 0x65, 0x3a, + 0x08, 0x88, 0xa0, 0x1f, 0x00, 0xe8, 0xa0, 0x1f, 0x00, 0x22, 0x53, 0x0a, 0x19, 0x56, 0x61, 0x6c, + 0x41, 0x64, 0x64, 0x72, 0x73, 0x4f, 0x66, 0x52, 0x6f, 0x74, 0x61, 0x74, 0x65, 0x64, 0x43, 0x6f, + 0x6e, 0x73, 0x4b, 0x65, 0x79, 0x73, 0x12, 0x36, 0x0a, 0x09, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, + 0x73, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x42, 0x18, 0xd2, 0xb4, 0x2d, 0x14, 0x63, + 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, + 0x69, 0x6e, 0x67, 0x52, 0x09, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x2a, 0xb6, + 0x01, 0x0a, 0x0a, 0x42, 0x6f, 0x6e, 0x64, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x2c, 0x0a, + 0x17, 0x42, 0x4f, 0x4e, 0x44, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x55, 0x4e, 0x53, + 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x1a, 0x0f, 0x8a, 0x9d, 0x20, 0x0b, + 0x55, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x64, 0x12, 0x26, 0x0a, 0x14, 0x42, + 0x4f, 0x4e, 0x44, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x55, 0x4e, 0x42, 0x4f, 0x4e, + 0x44, 0x45, 0x44, 0x10, 0x01, 0x1a, 0x0c, 0x8a, 0x9d, 0x20, 0x08, 0x55, 0x6e, 0x62, 0x6f, 0x6e, + 0x64, 0x65, 0x64, 0x12, 0x28, 0x0a, 0x15, 0x42, 0x4f, 0x4e, 0x44, 0x5f, 0x53, 0x54, 0x41, 0x54, + 0x55, 0x53, 0x5f, 0x55, 0x4e, 0x42, 0x4f, 0x4e, 0x44, 0x49, 0x4e, 0x47, 0x10, 0x02, 0x1a, 0x0d, + 0x8a, 0x9d, 0x20, 0x09, 0x55, 0x6e, 0x62, 0x6f, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x12, 0x22, 0x0a, + 0x12, 0x42, 0x4f, 0x4e, 0x44, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x42, 0x4f, 0x4e, + 0x44, 0x45, 0x44, 0x10, 0x03, 0x1a, 0x0a, 0x8a, 0x9d, 0x20, 0x06, 0x42, 0x6f, 0x6e, 0x64, 0x65, + 0x64, 0x1a, 0x04, 0x88, 0xa3, 0x1e, 0x00, 0x2a, 0x5d, 0x0a, 0x0a, 0x49, 0x6e, 0x66, 0x72, 0x61, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1a, 0x0a, 0x16, 0x49, 0x4e, 0x46, 0x52, 0x41, 0x43, 0x54, + 0x49, 0x4f, 0x4e, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, + 0x00, 0x12, 0x1a, 0x0a, 0x16, 0x49, 0x4e, 0x46, 0x52, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, + 0x44, 0x4f, 0x55, 0x42, 0x4c, 0x45, 0x5f, 0x53, 0x49, 0x47, 0x4e, 0x10, 0x01, 0x12, 0x17, 0x0a, + 0x13, 0x49, 0x4e, 0x46, 0x52, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x44, 0x4f, 0x57, 0x4e, + 0x54, 0x49, 0x4d, 0x45, 0x10, 0x02, 0x42, 0xdc, 0x01, 0x0a, 0x1a, 0x63, 0x6f, 0x6d, 0x2e, 0x63, + 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x31, + 0x62, 0x65, 0x74, 0x61, 0x31, 0x42, 0x0c, 0x53, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x50, 0x72, + 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x36, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x73, 0x64, 0x6b, + 0x2e, 0x69, 0x6f, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x73, + 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x3b, 0x73, + 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0xa2, 0x02, 0x03, + 0x43, 0x53, 0x58, 0xaa, 0x02, 0x16, 0x43, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x53, 0x74, 0x61, + 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x56, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0xca, 0x02, 0x16, 0x43, + 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x5c, 0x53, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x5c, 0x56, 0x31, + 0x62, 0x65, 0x74, 0x61, 0x31, 0xe2, 0x02, 0x22, 0x43, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x5c, 0x53, + 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x5c, 0x56, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x5c, 0x47, + 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x18, 0x43, 0x6f, 0x73, + 0x6d, 0x6f, 0x73, 0x3a, 0x3a, 0x53, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x3a, 0x3a, 0x56, 0x31, + 0x62, 0x65, 0x74, 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -15863,7 +16552,7 @@ func file_cosmos_staking_v1beta1_staking_proto_rawDescGZIP() []byte { } var file_cosmos_staking_v1beta1_staking_proto_enumTypes = make([]protoimpl.EnumInfo, 2) -var file_cosmos_staking_v1beta1_staking_proto_msgTypes = make([]protoimpl.MessageInfo, 23) +var file_cosmos_staking_v1beta1_staking_proto_msgTypes = make([]protoimpl.MessageInfo, 24) var file_cosmos_staking_v1beta1_staking_proto_goTypes = []interface{}{ (BondStatus)(0), // 0: cosmos.staking.v1beta1.BondStatus (Infraction)(0), // 1: cosmos.staking.v1beta1.Infraction @@ -15871,64 +16560,66 @@ var file_cosmos_staking_v1beta1_staking_proto_goTypes = []interface{}{ (*CommissionRates)(nil), // 3: cosmos.staking.v1beta1.CommissionRates (*Commission)(nil), // 4: cosmos.staking.v1beta1.Commission (*Description)(nil), // 5: cosmos.staking.v1beta1.Description - (*Validator)(nil), // 6: cosmos.staking.v1beta1.Validator - (*ValAddresses)(nil), // 7: cosmos.staking.v1beta1.ValAddresses - (*DVPair)(nil), // 8: cosmos.staking.v1beta1.DVPair - (*DVPairs)(nil), // 9: cosmos.staking.v1beta1.DVPairs - (*DVVTriplet)(nil), // 10: cosmos.staking.v1beta1.DVVTriplet - (*DVVTriplets)(nil), // 11: cosmos.staking.v1beta1.DVVTriplets - (*Delegation)(nil), // 12: cosmos.staking.v1beta1.Delegation - (*UnbondingDelegation)(nil), // 13: cosmos.staking.v1beta1.UnbondingDelegation - (*UnbondingDelegationEntry)(nil), // 14: cosmos.staking.v1beta1.UnbondingDelegationEntry - (*RedelegationEntry)(nil), // 15: cosmos.staking.v1beta1.RedelegationEntry - (*Redelegation)(nil), // 16: cosmos.staking.v1beta1.Redelegation - (*Params)(nil), // 17: cosmos.staking.v1beta1.Params - (*DelegationResponse)(nil), // 18: cosmos.staking.v1beta1.DelegationResponse - (*RedelegationEntryResponse)(nil), // 19: cosmos.staking.v1beta1.RedelegationEntryResponse - (*RedelegationResponse)(nil), // 20: cosmos.staking.v1beta1.RedelegationResponse - (*Pool)(nil), // 21: cosmos.staking.v1beta1.Pool - (*ValidatorUpdates)(nil), // 22: cosmos.staking.v1beta1.ValidatorUpdates - (*ConsPubKeyRotationHistory)(nil), // 23: cosmos.staking.v1beta1.ConsPubKeyRotationHistory - (*ValAddrsOfRotatedConsKeys)(nil), // 24: cosmos.staking.v1beta1.ValAddrsOfRotatedConsKeys - (*v1.Header)(nil), // 25: cometbft.types.v1.Header - (*timestamppb.Timestamp)(nil), // 26: google.protobuf.Timestamp - (*anypb.Any)(nil), // 27: google.protobuf.Any - (*durationpb.Duration)(nil), // 28: google.protobuf.Duration - (*v1beta1.Coin)(nil), // 29: cosmos.base.v1beta1.Coin - (*v11.ValidatorUpdate)(nil), // 30: cometbft.abci.v1.ValidatorUpdate + (*Metadata)(nil), // 6: cosmos.staking.v1beta1.Metadata + (*Validator)(nil), // 7: cosmos.staking.v1beta1.Validator + (*ValAddresses)(nil), // 8: cosmos.staking.v1beta1.ValAddresses + (*DVPair)(nil), // 9: cosmos.staking.v1beta1.DVPair + (*DVPairs)(nil), // 10: cosmos.staking.v1beta1.DVPairs + (*DVVTriplet)(nil), // 11: cosmos.staking.v1beta1.DVVTriplet + (*DVVTriplets)(nil), // 12: cosmos.staking.v1beta1.DVVTriplets + (*Delegation)(nil), // 13: cosmos.staking.v1beta1.Delegation + (*UnbondingDelegation)(nil), // 14: cosmos.staking.v1beta1.UnbondingDelegation + (*UnbondingDelegationEntry)(nil), // 15: cosmos.staking.v1beta1.UnbondingDelegationEntry + (*RedelegationEntry)(nil), // 16: cosmos.staking.v1beta1.RedelegationEntry + (*Redelegation)(nil), // 17: cosmos.staking.v1beta1.Redelegation + (*Params)(nil), // 18: cosmos.staking.v1beta1.Params + (*DelegationResponse)(nil), // 19: cosmos.staking.v1beta1.DelegationResponse + (*RedelegationEntryResponse)(nil), // 20: cosmos.staking.v1beta1.RedelegationEntryResponse + (*RedelegationResponse)(nil), // 21: cosmos.staking.v1beta1.RedelegationResponse + (*Pool)(nil), // 22: cosmos.staking.v1beta1.Pool + (*ValidatorUpdates)(nil), // 23: cosmos.staking.v1beta1.ValidatorUpdates + (*ConsPubKeyRotationHistory)(nil), // 24: cosmos.staking.v1beta1.ConsPubKeyRotationHistory + (*ValAddrsOfRotatedConsKeys)(nil), // 25: cosmos.staking.v1beta1.ValAddrsOfRotatedConsKeys + (*v1.Header)(nil), // 26: cometbft.types.v1.Header + (*timestamppb.Timestamp)(nil), // 27: google.protobuf.Timestamp + (*anypb.Any)(nil), // 28: google.protobuf.Any + (*durationpb.Duration)(nil), // 29: google.protobuf.Duration + (*v1beta1.Coin)(nil), // 30: cosmos.base.v1beta1.Coin + (*v11.ValidatorUpdate)(nil), // 31: cometbft.abci.v1.ValidatorUpdate } var file_cosmos_staking_v1beta1_staking_proto_depIdxs = []int32{ - 25, // 0: cosmos.staking.v1beta1.HistoricalInfo.header:type_name -> cometbft.types.v1.Header - 6, // 1: cosmos.staking.v1beta1.HistoricalInfo.valset:type_name -> cosmos.staking.v1beta1.Validator + 26, // 0: cosmos.staking.v1beta1.HistoricalInfo.header:type_name -> cometbft.types.v1.Header + 7, // 1: cosmos.staking.v1beta1.HistoricalInfo.valset:type_name -> cosmos.staking.v1beta1.Validator 3, // 2: cosmos.staking.v1beta1.Commission.commission_rates:type_name -> cosmos.staking.v1beta1.CommissionRates - 26, // 3: cosmos.staking.v1beta1.Commission.update_time:type_name -> google.protobuf.Timestamp - 27, // 4: cosmos.staking.v1beta1.Validator.consensus_pubkey:type_name -> google.protobuf.Any - 0, // 5: cosmos.staking.v1beta1.Validator.status:type_name -> cosmos.staking.v1beta1.BondStatus - 5, // 6: cosmos.staking.v1beta1.Validator.description:type_name -> cosmos.staking.v1beta1.Description - 26, // 7: cosmos.staking.v1beta1.Validator.unbonding_time:type_name -> google.protobuf.Timestamp - 4, // 8: cosmos.staking.v1beta1.Validator.commission:type_name -> cosmos.staking.v1beta1.Commission - 8, // 9: cosmos.staking.v1beta1.DVPairs.pairs:type_name -> cosmos.staking.v1beta1.DVPair - 10, // 10: cosmos.staking.v1beta1.DVVTriplets.triplets:type_name -> cosmos.staking.v1beta1.DVVTriplet - 14, // 11: cosmos.staking.v1beta1.UnbondingDelegation.entries:type_name -> cosmos.staking.v1beta1.UnbondingDelegationEntry - 26, // 12: cosmos.staking.v1beta1.UnbondingDelegationEntry.completion_time:type_name -> google.protobuf.Timestamp - 26, // 13: cosmos.staking.v1beta1.RedelegationEntry.completion_time:type_name -> google.protobuf.Timestamp - 15, // 14: cosmos.staking.v1beta1.Redelegation.entries:type_name -> cosmos.staking.v1beta1.RedelegationEntry - 28, // 15: cosmos.staking.v1beta1.Params.unbonding_time:type_name -> google.protobuf.Duration - 29, // 16: cosmos.staking.v1beta1.Params.key_rotation_fee:type_name -> cosmos.base.v1beta1.Coin - 12, // 17: cosmos.staking.v1beta1.DelegationResponse.delegation:type_name -> cosmos.staking.v1beta1.Delegation - 29, // 18: cosmos.staking.v1beta1.DelegationResponse.balance:type_name -> cosmos.base.v1beta1.Coin - 15, // 19: cosmos.staking.v1beta1.RedelegationEntryResponse.redelegation_entry:type_name -> cosmos.staking.v1beta1.RedelegationEntry - 16, // 20: cosmos.staking.v1beta1.RedelegationResponse.redelegation:type_name -> cosmos.staking.v1beta1.Redelegation - 19, // 21: cosmos.staking.v1beta1.RedelegationResponse.entries:type_name -> cosmos.staking.v1beta1.RedelegationEntryResponse - 30, // 22: cosmos.staking.v1beta1.ValidatorUpdates.updates:type_name -> cometbft.abci.v1.ValidatorUpdate - 27, // 23: cosmos.staking.v1beta1.ConsPubKeyRotationHistory.old_cons_pubkey:type_name -> google.protobuf.Any - 27, // 24: cosmos.staking.v1beta1.ConsPubKeyRotationHistory.new_cons_pubkey:type_name -> google.protobuf.Any - 29, // 25: cosmos.staking.v1beta1.ConsPubKeyRotationHistory.fee:type_name -> cosmos.base.v1beta1.Coin - 26, // [26:26] is the sub-list for method output_type - 26, // [26:26] is the sub-list for method input_type - 26, // [26:26] is the sub-list for extension type_name - 26, // [26:26] is the sub-list for extension extendee - 0, // [0:26] is the sub-list for field type_name + 27, // 3: cosmos.staking.v1beta1.Commission.update_time:type_name -> google.protobuf.Timestamp + 6, // 4: cosmos.staking.v1beta1.Description.metadata:type_name -> cosmos.staking.v1beta1.Metadata + 28, // 5: cosmos.staking.v1beta1.Validator.consensus_pubkey:type_name -> google.protobuf.Any + 0, // 6: cosmos.staking.v1beta1.Validator.status:type_name -> cosmos.staking.v1beta1.BondStatus + 5, // 7: cosmos.staking.v1beta1.Validator.description:type_name -> cosmos.staking.v1beta1.Description + 27, // 8: cosmos.staking.v1beta1.Validator.unbonding_time:type_name -> google.protobuf.Timestamp + 4, // 9: cosmos.staking.v1beta1.Validator.commission:type_name -> cosmos.staking.v1beta1.Commission + 9, // 10: cosmos.staking.v1beta1.DVPairs.pairs:type_name -> cosmos.staking.v1beta1.DVPair + 11, // 11: cosmos.staking.v1beta1.DVVTriplets.triplets:type_name -> cosmos.staking.v1beta1.DVVTriplet + 15, // 12: cosmos.staking.v1beta1.UnbondingDelegation.entries:type_name -> cosmos.staking.v1beta1.UnbondingDelegationEntry + 27, // 13: cosmos.staking.v1beta1.UnbondingDelegationEntry.completion_time:type_name -> google.protobuf.Timestamp + 27, // 14: cosmos.staking.v1beta1.RedelegationEntry.completion_time:type_name -> google.protobuf.Timestamp + 16, // 15: cosmos.staking.v1beta1.Redelegation.entries:type_name -> cosmos.staking.v1beta1.RedelegationEntry + 29, // 16: cosmos.staking.v1beta1.Params.unbonding_time:type_name -> google.protobuf.Duration + 30, // 17: cosmos.staking.v1beta1.Params.key_rotation_fee:type_name -> cosmos.base.v1beta1.Coin + 13, // 18: cosmos.staking.v1beta1.DelegationResponse.delegation:type_name -> cosmos.staking.v1beta1.Delegation + 30, // 19: cosmos.staking.v1beta1.DelegationResponse.balance:type_name -> cosmos.base.v1beta1.Coin + 16, // 20: cosmos.staking.v1beta1.RedelegationEntryResponse.redelegation_entry:type_name -> cosmos.staking.v1beta1.RedelegationEntry + 17, // 21: cosmos.staking.v1beta1.RedelegationResponse.redelegation:type_name -> cosmos.staking.v1beta1.Redelegation + 20, // 22: cosmos.staking.v1beta1.RedelegationResponse.entries:type_name -> cosmos.staking.v1beta1.RedelegationEntryResponse + 31, // 23: cosmos.staking.v1beta1.ValidatorUpdates.updates:type_name -> cometbft.abci.v1.ValidatorUpdate + 28, // 24: cosmos.staking.v1beta1.ConsPubKeyRotationHistory.old_cons_pubkey:type_name -> google.protobuf.Any + 28, // 25: cosmos.staking.v1beta1.ConsPubKeyRotationHistory.new_cons_pubkey:type_name -> google.protobuf.Any + 30, // 26: cosmos.staking.v1beta1.ConsPubKeyRotationHistory.fee:type_name -> cosmos.base.v1beta1.Coin + 27, // [27:27] is the sub-list for method output_type + 27, // [27:27] is the sub-list for method input_type + 27, // [27:27] is the sub-list for extension type_name + 27, // [27:27] is the sub-list for extension extendee + 0, // [0:27] is the sub-list for field type_name } func init() { file_cosmos_staking_v1beta1_staking_proto_init() } @@ -15986,7 +16677,7 @@ func file_cosmos_staking_v1beta1_staking_proto_init() { } } file_cosmos_staking_v1beta1_staking_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Validator); i { + switch v := v.(*Metadata); i { case 0: return &v.state case 1: @@ -15998,7 +16689,7 @@ func file_cosmos_staking_v1beta1_staking_proto_init() { } } file_cosmos_staking_v1beta1_staking_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ValAddresses); i { + switch v := v.(*Validator); i { case 0: return &v.state case 1: @@ -16010,7 +16701,7 @@ func file_cosmos_staking_v1beta1_staking_proto_init() { } } file_cosmos_staking_v1beta1_staking_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DVPair); i { + switch v := v.(*ValAddresses); i { case 0: return &v.state case 1: @@ -16022,7 +16713,7 @@ func file_cosmos_staking_v1beta1_staking_proto_init() { } } file_cosmos_staking_v1beta1_staking_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DVPairs); i { + switch v := v.(*DVPair); i { case 0: return &v.state case 1: @@ -16034,7 +16725,7 @@ func file_cosmos_staking_v1beta1_staking_proto_init() { } } file_cosmos_staking_v1beta1_staking_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DVVTriplet); i { + switch v := v.(*DVPairs); i { case 0: return &v.state case 1: @@ -16046,7 +16737,7 @@ func file_cosmos_staking_v1beta1_staking_proto_init() { } } file_cosmos_staking_v1beta1_staking_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DVVTriplets); i { + switch v := v.(*DVVTriplet); i { case 0: return &v.state case 1: @@ -16058,7 +16749,7 @@ func file_cosmos_staking_v1beta1_staking_proto_init() { } } file_cosmos_staking_v1beta1_staking_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Delegation); i { + switch v := v.(*DVVTriplets); i { case 0: return &v.state case 1: @@ -16070,7 +16761,7 @@ func file_cosmos_staking_v1beta1_staking_proto_init() { } } file_cosmos_staking_v1beta1_staking_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*UnbondingDelegation); i { + switch v := v.(*Delegation); i { case 0: return &v.state case 1: @@ -16082,7 +16773,7 @@ func file_cosmos_staking_v1beta1_staking_proto_init() { } } file_cosmos_staking_v1beta1_staking_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*UnbondingDelegationEntry); i { + switch v := v.(*UnbondingDelegation); i { case 0: return &v.state case 1: @@ -16094,7 +16785,7 @@ func file_cosmos_staking_v1beta1_staking_proto_init() { } } file_cosmos_staking_v1beta1_staking_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RedelegationEntry); i { + switch v := v.(*UnbondingDelegationEntry); i { case 0: return &v.state case 1: @@ -16106,7 +16797,7 @@ func file_cosmos_staking_v1beta1_staking_proto_init() { } } file_cosmos_staking_v1beta1_staking_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Redelegation); i { + switch v := v.(*RedelegationEntry); i { case 0: return &v.state case 1: @@ -16118,7 +16809,7 @@ func file_cosmos_staking_v1beta1_staking_proto_init() { } } file_cosmos_staking_v1beta1_staking_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Params); i { + switch v := v.(*Redelegation); i { case 0: return &v.state case 1: @@ -16130,7 +16821,7 @@ func file_cosmos_staking_v1beta1_staking_proto_init() { } } file_cosmos_staking_v1beta1_staking_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DelegationResponse); i { + switch v := v.(*Params); i { case 0: return &v.state case 1: @@ -16142,7 +16833,7 @@ func file_cosmos_staking_v1beta1_staking_proto_init() { } } file_cosmos_staking_v1beta1_staking_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RedelegationEntryResponse); i { + switch v := v.(*DelegationResponse); i { case 0: return &v.state case 1: @@ -16154,7 +16845,7 @@ func file_cosmos_staking_v1beta1_staking_proto_init() { } } file_cosmos_staking_v1beta1_staking_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RedelegationResponse); i { + switch v := v.(*RedelegationEntryResponse); i { case 0: return &v.state case 1: @@ -16166,7 +16857,7 @@ func file_cosmos_staking_v1beta1_staking_proto_init() { } } file_cosmos_staking_v1beta1_staking_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Pool); i { + switch v := v.(*RedelegationResponse); i { case 0: return &v.state case 1: @@ -16178,7 +16869,7 @@ func file_cosmos_staking_v1beta1_staking_proto_init() { } } file_cosmos_staking_v1beta1_staking_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ValidatorUpdates); i { + switch v := v.(*Pool); i { case 0: return &v.state case 1: @@ -16190,7 +16881,7 @@ func file_cosmos_staking_v1beta1_staking_proto_init() { } } file_cosmos_staking_v1beta1_staking_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ConsPubKeyRotationHistory); i { + switch v := v.(*ValidatorUpdates); i { case 0: return &v.state case 1: @@ -16202,6 +16893,18 @@ func file_cosmos_staking_v1beta1_staking_proto_init() { } } file_cosmos_staking_v1beta1_staking_proto_msgTypes[22].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ConsPubKeyRotationHistory); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cosmos_staking_v1beta1_staking_proto_msgTypes[23].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ValAddrsOfRotatedConsKeys); i { case 0: return &v.state @@ -16220,7 +16923,7 @@ func file_cosmos_staking_v1beta1_staking_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_cosmos_staking_v1beta1_staking_proto_rawDesc, NumEnums: 2, - NumMessages: 23, + NumMessages: 24, NumExtensions: 0, NumServices: 0, }, diff --git a/api/cosmos/tx/config/v1/config.pulsar.go b/api/cosmos/tx/config/v1/config.pulsar.go index c0b353c4367f..0c4daa5dff10 100644 --- a/api/cosmos/tx/config/v1/config.pulsar.go +++ b/api/cosmos/tx/config/v1/config.pulsar.go @@ -14,16 +14,12 @@ import ( ) var ( - md_Config protoreflect.MessageDescriptor - fd_Config_skip_ante_handler protoreflect.FieldDescriptor - fd_Config_skip_post_handler protoreflect.FieldDescriptor + md_Config protoreflect.MessageDescriptor ) func init() { file_cosmos_tx_config_v1_config_proto_init() md_Config = File_cosmos_tx_config_v1_config_proto.Messages().ByName("Config") - fd_Config_skip_ante_handler = md_Config.Fields().ByName("skip_ante_handler") - fd_Config_skip_post_handler = md_Config.Fields().ByName("skip_post_handler") } var _ protoreflect.Message = (*fastReflection_Config)(nil) @@ -91,18 +87,6 @@ func (x *fastReflection_Config) Interface() protoreflect.ProtoMessage { // While iterating, mutating operations may only be performed // on the current field descriptor. func (x *fastReflection_Config) Range(f func(protoreflect.FieldDescriptor, protoreflect.Value) bool) { - if x.SkipAnteHandler != false { - value := protoreflect.ValueOfBool(x.SkipAnteHandler) - if !f(fd_Config_skip_ante_handler, value) { - return - } - } - if x.SkipPostHandler != false { - value := protoreflect.ValueOfBool(x.SkipPostHandler) - if !f(fd_Config_skip_post_handler, value) { - return - } - } } // Has reports whether a field is populated. @@ -118,10 +102,6 @@ func (x *fastReflection_Config) Range(f func(protoreflect.FieldDescriptor, proto // a repeated field is populated if it is non-empty. func (x *fastReflection_Config) Has(fd protoreflect.FieldDescriptor) bool { switch fd.FullName() { - case "cosmos.tx.config.v1.Config.skip_ante_handler": - return x.SkipAnteHandler != false - case "cosmos.tx.config.v1.Config.skip_post_handler": - return x.SkipPostHandler != false default: if fd.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.tx.config.v1.Config")) @@ -138,10 +118,6 @@ func (x *fastReflection_Config) Has(fd protoreflect.FieldDescriptor) bool { // Clear is a mutating operation and unsafe for concurrent use. func (x *fastReflection_Config) Clear(fd protoreflect.FieldDescriptor) { switch fd.FullName() { - case "cosmos.tx.config.v1.Config.skip_ante_handler": - x.SkipAnteHandler = false - case "cosmos.tx.config.v1.Config.skip_post_handler": - x.SkipPostHandler = false default: if fd.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.tx.config.v1.Config")) @@ -158,12 +134,6 @@ func (x *fastReflection_Config) Clear(fd protoreflect.FieldDescriptor) { // of the value; to obtain a mutable reference, use Mutable. func (x *fastReflection_Config) Get(descriptor protoreflect.FieldDescriptor) protoreflect.Value { switch descriptor.FullName() { - case "cosmos.tx.config.v1.Config.skip_ante_handler": - value := x.SkipAnteHandler - return protoreflect.ValueOfBool(value) - case "cosmos.tx.config.v1.Config.skip_post_handler": - value := x.SkipPostHandler - return protoreflect.ValueOfBool(value) default: if descriptor.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.tx.config.v1.Config")) @@ -184,10 +154,6 @@ func (x *fastReflection_Config) Get(descriptor protoreflect.FieldDescriptor) pro // Set is a mutating operation and unsafe for concurrent use. func (x *fastReflection_Config) Set(fd protoreflect.FieldDescriptor, value protoreflect.Value) { switch fd.FullName() { - case "cosmos.tx.config.v1.Config.skip_ante_handler": - x.SkipAnteHandler = value.Bool() - case "cosmos.tx.config.v1.Config.skip_post_handler": - x.SkipPostHandler = value.Bool() default: if fd.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.tx.config.v1.Config")) @@ -208,10 +174,6 @@ func (x *fastReflection_Config) Set(fd protoreflect.FieldDescriptor, value proto // Mutable is a mutating operation and unsafe for concurrent use. func (x *fastReflection_Config) Mutable(fd protoreflect.FieldDescriptor) protoreflect.Value { switch fd.FullName() { - case "cosmos.tx.config.v1.Config.skip_ante_handler": - panic(fmt.Errorf("field skip_ante_handler of message cosmos.tx.config.v1.Config is not mutable")) - case "cosmos.tx.config.v1.Config.skip_post_handler": - panic(fmt.Errorf("field skip_post_handler of message cosmos.tx.config.v1.Config is not mutable")) default: if fd.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.tx.config.v1.Config")) @@ -225,10 +187,6 @@ func (x *fastReflection_Config) Mutable(fd protoreflect.FieldDescriptor) protore // For lists, maps, and messages, this returns a new, empty, mutable value. func (x *fastReflection_Config) NewField(fd protoreflect.FieldDescriptor) protoreflect.Value { switch fd.FullName() { - case "cosmos.tx.config.v1.Config.skip_ante_handler": - return protoreflect.ValueOfBool(false) - case "cosmos.tx.config.v1.Config.skip_post_handler": - return protoreflect.ValueOfBool(false) default: if fd.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.tx.config.v1.Config")) @@ -298,12 +256,6 @@ func (x *fastReflection_Config) ProtoMethods() *protoiface.Methods { var n int var l int _ = l - if x.SkipAnteHandler { - n += 2 - } - if x.SkipPostHandler { - n += 2 - } if x.unknownFields != nil { n += len(x.unknownFields) } @@ -333,26 +285,6 @@ func (x *fastReflection_Config) ProtoMethods() *protoiface.Methods { i -= len(x.unknownFields) copy(dAtA[i:], x.unknownFields) } - if x.SkipPostHandler { - i-- - if x.SkipPostHandler { - dAtA[i] = 1 - } else { - dAtA[i] = 0 - } - i-- - dAtA[i] = 0x10 - } - if x.SkipAnteHandler { - i-- - if x.SkipAnteHandler { - dAtA[i] = 1 - } else { - dAtA[i] = 0 - } - i-- - dAtA[i] = 0x8 - } if input.Buf != nil { input.Buf = append(input.Buf, dAtA...) } else { @@ -402,46 +334,6 @@ func (x *fastReflection_Config) ProtoMethods() *protoiface.Methods { return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: Config: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { - case 1: - if wireType != 0 { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field SkipAnteHandler", wireType) - } - var v int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow - } - if iNdEx >= l { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - v |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - x.SkipAnteHandler = bool(v != 0) - case 2: - if wireType != 0 { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field SkipPostHandler", wireType) - } - var v int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow - } - if iNdEx >= l { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - v |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - x.SkipPostHandler = bool(v != 0) default: iNdEx = preIndex skippy, err := runtime.Skip(dAtA[iNdEx:]) @@ -495,13 +387,6 @@ type Config struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - - // skip_ante_handler defines whether the ante handler registration should be skipped in case an app wants to override - // this functionality. - SkipAnteHandler bool `protobuf:"varint,1,opt,name=skip_ante_handler,json=skipAnteHandler,proto3" json:"skip_ante_handler,omitempty"` - // skip_post_handler defines whether the post handler registration should be skipped in case an app wants to override - // this functionality. - SkipPostHandler bool `protobuf:"varint,2,opt,name=skip_post_handler,json=skipPostHandler,proto3" json:"skip_post_handler,omitempty"` } func (x *Config) Reset() { @@ -524,20 +409,6 @@ func (*Config) Descriptor() ([]byte, []int) { return file_cosmos_tx_config_v1_config_proto_rawDescGZIP(), []int{0} } -func (x *Config) GetSkipAnteHandler() bool { - if x != nil { - return x.SkipAnteHandler - } - return false -} - -func (x *Config) GetSkipPostHandler() bool { - if x != nil { - return x.SkipPostHandler - } - return false -} - var File_cosmos_tx_config_v1_config_proto protoreflect.FileDescriptor var file_cosmos_tx_config_v1_config_proto_rawDesc = []byte{ @@ -546,29 +417,24 @@ var file_cosmos_tx_config_v1_config_proto_rawDesc = []byte{ 0x74, 0x6f, 0x12, 0x13, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x74, 0x78, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x76, 0x31, 0x1a, 0x20, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x6d, 0x6f, 0x64, - 0x75, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x90, 0x01, 0x0a, 0x06, 0x43, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x12, 0x2a, 0x0a, 0x11, 0x73, 0x6b, 0x69, 0x70, 0x5f, 0x61, 0x6e, 0x74, - 0x65, 0x5f, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, - 0x0f, 0x73, 0x6b, 0x69, 0x70, 0x41, 0x6e, 0x74, 0x65, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, - 0x12, 0x2a, 0x0a, 0x11, 0x73, 0x6b, 0x69, 0x70, 0x5f, 0x70, 0x6f, 0x73, 0x74, 0x5f, 0x68, 0x61, - 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x73, 0x6b, 0x69, - 0x70, 0x50, 0x6f, 0x73, 0x74, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x3a, 0x2e, 0xba, 0xc0, - 0x96, 0xda, 0x01, 0x28, 0x0a, 0x26, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, - 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2d, 0x73, - 0x64, 0x6b, 0x2f, 0x78, 0x2f, 0x61, 0x75, 0x74, 0x68, 0x2f, 0x74, 0x78, 0x42, 0xc4, 0x01, 0x0a, - 0x17, 0x63, 0x6f, 0x6d, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x74, 0x78, 0x2e, 0x63, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x76, 0x31, 0x42, 0x0b, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x2d, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x73, - 0x64, 0x6b, 0x2e, 0x69, 0x6f, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, - 0x2f, 0x74, 0x78, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2f, 0x76, 0x31, 0x3b, 0x63, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x76, 0x31, 0xa2, 0x02, 0x03, 0x43, 0x54, 0x43, 0xaa, 0x02, 0x13, 0x43, - 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x54, 0x78, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, - 0x56, 0x31, 0xca, 0x02, 0x13, 0x43, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x5c, 0x54, 0x78, 0x5c, 0x43, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x1f, 0x43, 0x6f, 0x73, 0x6d, 0x6f, - 0x73, 0x5c, 0x54, 0x78, 0x5c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5c, 0x56, 0x31, 0x5c, 0x47, - 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x16, 0x43, 0x6f, 0x73, - 0x6d, 0x6f, 0x73, 0x3a, 0x3a, 0x54, 0x78, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x3a, - 0x3a, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x75, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x38, 0x0a, 0x06, 0x43, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x3a, 0x2e, 0xba, 0xc0, 0x96, 0xda, 0x01, 0x28, 0x0a, 0x26, 0x67, 0x69, 0x74, + 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x63, + 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2d, 0x73, 0x64, 0x6b, 0x2f, 0x78, 0x2f, 0x61, 0x75, 0x74, 0x68, + 0x2f, 0x74, 0x78, 0x42, 0xc4, 0x01, 0x0a, 0x17, 0x63, 0x6f, 0x6d, 0x2e, 0x63, 0x6f, 0x73, 0x6d, + 0x6f, 0x73, 0x2e, 0x74, 0x78, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x76, 0x31, 0x42, + 0x0b, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x2d, + 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x73, 0x64, 0x6b, 0x2e, 0x69, 0x6f, 0x2f, 0x61, 0x70, 0x69, + 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x74, 0x78, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x2f, 0x76, 0x31, 0x3b, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x76, 0x31, 0xa2, 0x02, 0x03, + 0x43, 0x54, 0x43, 0xaa, 0x02, 0x13, 0x43, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x54, 0x78, 0x2e, + 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x13, 0x43, 0x6f, 0x73, 0x6d, + 0x6f, 0x73, 0x5c, 0x54, 0x78, 0x5c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5c, 0x56, 0x31, 0xe2, + 0x02, 0x1f, 0x43, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x5c, 0x54, 0x78, 0x5c, 0x43, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, + 0x61, 0xea, 0x02, 0x16, 0x43, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x3a, 0x3a, 0x54, 0x78, 0x3a, 0x3a, + 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x33, } var ( diff --git a/api/cosmos/validate/module/v1/module.pulsar.go b/api/cosmos/validate/module/v1/module.pulsar.go new file mode 100644 index 000000000000..2c27aa07d75e --- /dev/null +++ b/api/cosmos/validate/module/v1/module.pulsar.go @@ -0,0 +1,504 @@ +// Code generated by protoc-gen-go-pulsar. DO NOT EDIT. +package modulev1 + +import ( + _ "cosmossdk.io/api/cosmos/app/v1alpha1" + fmt "fmt" + runtime "github.com/cosmos/cosmos-proto/runtime" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoiface "google.golang.org/protobuf/runtime/protoiface" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + io "io" + reflect "reflect" + sync "sync" +) + +var ( + md_Module protoreflect.MessageDescriptor +) + +func init() { + file_cosmos_validate_module_v1_module_proto_init() + md_Module = File_cosmos_validate_module_v1_module_proto.Messages().ByName("Module") +} + +var _ protoreflect.Message = (*fastReflection_Module)(nil) + +type fastReflection_Module Module + +func (x *Module) ProtoReflect() protoreflect.Message { + return (*fastReflection_Module)(x) +} + +func (x *Module) slowProtoReflect() protoreflect.Message { + mi := &file_cosmos_validate_module_v1_module_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +var _fastReflection_Module_messageType fastReflection_Module_messageType +var _ protoreflect.MessageType = fastReflection_Module_messageType{} + +type fastReflection_Module_messageType struct{} + +func (x fastReflection_Module_messageType) Zero() protoreflect.Message { + return (*fastReflection_Module)(nil) +} +func (x fastReflection_Module_messageType) New() protoreflect.Message { + return new(fastReflection_Module) +} +func (x fastReflection_Module_messageType) Descriptor() protoreflect.MessageDescriptor { + return md_Module +} + +// Descriptor returns message descriptor, which contains only the protobuf +// type information for the message. +func (x *fastReflection_Module) Descriptor() protoreflect.MessageDescriptor { + return md_Module +} + +// Type returns the message type, which encapsulates both Go and protobuf +// type information. If the Go type information is not needed, +// it is recommended that the message descriptor be used instead. +func (x *fastReflection_Module) Type() protoreflect.MessageType { + return _fastReflection_Module_messageType +} + +// New returns a newly allocated and mutable empty message. +func (x *fastReflection_Module) New() protoreflect.Message { + return new(fastReflection_Module) +} + +// Interface unwraps the message reflection interface and +// returns the underlying ProtoMessage interface. +func (x *fastReflection_Module) Interface() protoreflect.ProtoMessage { + return (*Module)(x) +} + +// Range iterates over every populated field in an undefined order, +// calling f for each field descriptor and value encountered. +// Range returns immediately if f returns false. +// While iterating, mutating operations may only be performed +// on the current field descriptor. +func (x *fastReflection_Module) Range(f func(protoreflect.FieldDescriptor, protoreflect.Value) bool) { +} + +// Has reports whether a field is populated. +// +// Some fields have the property of nullability where it is possible to +// distinguish between the default value of a field and whether the field +// was explicitly populated with the default value. Singular message fields, +// member fields of a oneof, and proto2 scalar fields are nullable. Such +// fields are populated only if explicitly set. +// +// In other cases (aside from the nullable cases above), +// a proto3 scalar field is populated if it contains a non-zero value, and +// a repeated field is populated if it is non-empty. +func (x *fastReflection_Module) Has(fd protoreflect.FieldDescriptor) bool { + switch fd.FullName() { + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.validate.module.v1.Module")) + } + panic(fmt.Errorf("message cosmos.validate.module.v1.Module does not contain field %s", fd.FullName())) + } +} + +// Clear clears the field such that a subsequent Has call reports false. +// +// Clearing an extension field clears both the extension type and value +// associated with the given field number. +// +// Clear is a mutating operation and unsafe for concurrent use. +func (x *fastReflection_Module) Clear(fd protoreflect.FieldDescriptor) { + switch fd.FullName() { + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.validate.module.v1.Module")) + } + panic(fmt.Errorf("message cosmos.validate.module.v1.Module does not contain field %s", fd.FullName())) + } +} + +// Get retrieves the value for a field. +// +// For unpopulated scalars, it returns the default value, where +// the default value of a bytes scalar is guaranteed to be a copy. +// For unpopulated composite types, it returns an empty, read-only view +// of the value; to obtain a mutable reference, use Mutable. +func (x *fastReflection_Module) Get(descriptor protoreflect.FieldDescriptor) protoreflect.Value { + switch descriptor.FullName() { + default: + if descriptor.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.validate.module.v1.Module")) + } + panic(fmt.Errorf("message cosmos.validate.module.v1.Module does not contain field %s", descriptor.FullName())) + } +} + +// Set stores the value for a field. +// +// For a field belonging to a oneof, it implicitly clears any other field +// that may be currently set within the same oneof. +// For extension fields, it implicitly stores the provided ExtensionType. +// When setting a composite type, it is unspecified whether the stored value +// aliases the source's memory in any way. If the composite value is an +// empty, read-only value, then it panics. +// +// Set is a mutating operation and unsafe for concurrent use. +func (x *fastReflection_Module) Set(fd protoreflect.FieldDescriptor, value protoreflect.Value) { + switch fd.FullName() { + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.validate.module.v1.Module")) + } + panic(fmt.Errorf("message cosmos.validate.module.v1.Module does not contain field %s", fd.FullName())) + } +} + +// Mutable returns a mutable reference to a composite type. +// +// If the field is unpopulated, it may allocate a composite value. +// For a field belonging to a oneof, it implicitly clears any other field +// that may be currently set within the same oneof. +// For extension fields, it implicitly stores the provided ExtensionType +// if not already stored. +// It panics if the field does not contain a composite type. +// +// Mutable is a mutating operation and unsafe for concurrent use. +func (x *fastReflection_Module) Mutable(fd protoreflect.FieldDescriptor) protoreflect.Value { + switch fd.FullName() { + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.validate.module.v1.Module")) + } + panic(fmt.Errorf("message cosmos.validate.module.v1.Module does not contain field %s", fd.FullName())) + } +} + +// NewField returns a new value that is assignable to the field +// for the given descriptor. For scalars, this returns the default value. +// For lists, maps, and messages, this returns a new, empty, mutable value. +func (x *fastReflection_Module) NewField(fd protoreflect.FieldDescriptor) protoreflect.Value { + switch fd.FullName() { + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.validate.module.v1.Module")) + } + panic(fmt.Errorf("message cosmos.validate.module.v1.Module does not contain field %s", fd.FullName())) + } +} + +// WhichOneof reports which field within the oneof is populated, +// returning nil if none are populated. +// It panics if the oneof descriptor does not belong to this message. +func (x *fastReflection_Module) WhichOneof(d protoreflect.OneofDescriptor) protoreflect.FieldDescriptor { + switch d.FullName() { + default: + panic(fmt.Errorf("%s is not a oneof field in cosmos.validate.module.v1.Module", d.FullName())) + } + panic("unreachable") +} + +// GetUnknown retrieves the entire list of unknown fields. +// The caller may only mutate the contents of the RawFields +// if the mutated bytes are stored back into the message with SetUnknown. +func (x *fastReflection_Module) GetUnknown() protoreflect.RawFields { + return x.unknownFields +} + +// SetUnknown stores an entire list of unknown fields. +// The raw fields must be syntactically valid according to the wire format. +// An implementation may panic if this is not the case. +// Once stored, the caller must not mutate the content of the RawFields. +// An empty RawFields may be passed to clear the fields. +// +// SetUnknown is a mutating operation and unsafe for concurrent use. +func (x *fastReflection_Module) SetUnknown(fields protoreflect.RawFields) { + x.unknownFields = fields +} + +// IsValid reports whether the message is valid. +// +// An invalid message is an empty, read-only value. +// +// An invalid message often corresponds to a nil pointer of the concrete +// message type, but the details are implementation dependent. +// Validity is not part of the protobuf data model, and may not +// be preserved in marshaling or other operations. +func (x *fastReflection_Module) IsValid() bool { + return x != nil +} + +// ProtoMethods returns optional fastReflectionFeature-path implementations of various operations. +// This method may return nil. +// +// The returned methods type is identical to +// "google.golang.org/protobuf/runtime/protoiface".Methods. +// Consult the protoiface package documentation for details. +func (x *fastReflection_Module) ProtoMethods() *protoiface.Methods { + size := func(input protoiface.SizeInput) protoiface.SizeOutput { + x := input.Message.Interface().(*Module) + if x == nil { + return protoiface.SizeOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Size: 0, + } + } + options := runtime.SizeInputToOptions(input) + _ = options + var n int + var l int + _ = l + if x.unknownFields != nil { + n += len(x.unknownFields) + } + return protoiface.SizeOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Size: n, + } + } + + marshal := func(input protoiface.MarshalInput) (protoiface.MarshalOutput, error) { + x := input.Message.Interface().(*Module) + if x == nil { + return protoiface.MarshalOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Buf: input.Buf, + }, nil + } + options := runtime.MarshalInputToOptions(input) + _ = options + size := options.Size(x) + dAtA := make([]byte, size) + i := len(dAtA) + _ = i + var l int + _ = l + if x.unknownFields != nil { + i -= len(x.unknownFields) + copy(dAtA[i:], x.unknownFields) + } + if input.Buf != nil { + input.Buf = append(input.Buf, dAtA...) + } else { + input.Buf = dAtA + } + return protoiface.MarshalOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Buf: input.Buf, + }, nil + } + unmarshal := func(input protoiface.UnmarshalInput) (protoiface.UnmarshalOutput, error) { + x := input.Message.Interface().(*Module) + if x == nil { + return protoiface.UnmarshalOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Flags: input.Flags, + }, nil + } + options := runtime.UnmarshalInputToOptions(input) + _ = options + dAtA := input.Buf + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow + } + if iNdEx >= l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, 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 protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: Module: wiretype end group for non-group") + } + if fieldNum <= 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: Module: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := runtime.Skip(dAtA[iNdEx:]) + if err != nil { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + if (iNdEx + skippy) > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + if !options.DiscardUnknown { + x.unknownFields = append(x.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + } + iNdEx += skippy + } + } + + if iNdEx > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, nil + } + return &protoiface.Methods{ + NoUnkeyedLiterals: struct{}{}, + Flags: protoiface.SupportMarshalDeterministic | protoiface.SupportUnmarshalDiscardUnknown, + Size: size, + Marshal: marshal, + Unmarshal: unmarshal, + Merge: nil, + CheckInitialized: nil, + } +} + +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.27.0 +// protoc (unknown) +// source: cosmos/validate/module/v1/module.proto + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// Module is the config object of the x/validate module. +type Module struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *Module) Reset() { + *x = Module{} + if protoimpl.UnsafeEnabled { + mi := &file_cosmos_validate_module_v1_module_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Module) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Module) ProtoMessage() {} + +// Deprecated: Use Module.ProtoReflect.Descriptor instead. +func (*Module) Descriptor() ([]byte, []int) { + return file_cosmos_validate_module_v1_module_proto_rawDescGZIP(), []int{0} +} + +var File_cosmos_validate_module_v1_module_proto protoreflect.FileDescriptor + +var file_cosmos_validate_module_v1_module_proto_rawDesc = []byte{ + 0x0a, 0x26, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, + 0x65, 0x2f, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x2f, 0x76, 0x31, 0x2f, 0x6d, 0x6f, 0x64, 0x75, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x19, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, + 0x2e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x2e, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, + 0x2e, 0x76, 0x31, 0x1a, 0x20, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x61, 0x70, 0x70, 0x2f, + 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x39, 0x0a, 0x06, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x3a, + 0x2f, 0xba, 0xc0, 0x96, 0xda, 0x01, 0x29, 0x0a, 0x27, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, + 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, + 0x73, 0x2d, 0x73, 0x64, 0x6b, 0x2f, 0x78, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, + 0x42, 0xe8, 0x01, 0x0a, 0x1d, 0x63, 0x6f, 0x6d, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, + 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x2e, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x2e, + 0x76, 0x31, 0x42, 0x0b, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, + 0x01, 0x5a, 0x33, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x73, 0x64, 0x6b, 0x2e, 0x69, 0x6f, 0x2f, + 0x61, 0x70, 0x69, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, + 0x61, 0x74, 0x65, 0x2f, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x2f, 0x76, 0x31, 0x3b, 0x6d, 0x6f, + 0x64, 0x75, 0x6c, 0x65, 0x76, 0x31, 0xa2, 0x02, 0x03, 0x43, 0x56, 0x4d, 0xaa, 0x02, 0x19, 0x43, + 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x2e, 0x4d, + 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x19, 0x43, 0x6f, 0x73, 0x6d, 0x6f, + 0x73, 0x5c, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x5c, 0x4d, 0x6f, 0x64, 0x75, 0x6c, + 0x65, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x25, 0x43, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x5c, 0x56, 0x61, + 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x5c, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x5c, 0x56, 0x31, + 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x1c, 0x43, + 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x3a, 0x3a, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x3a, + 0x3a, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x33, +} + +var ( + file_cosmos_validate_module_v1_module_proto_rawDescOnce sync.Once + file_cosmos_validate_module_v1_module_proto_rawDescData = file_cosmos_validate_module_v1_module_proto_rawDesc +) + +func file_cosmos_validate_module_v1_module_proto_rawDescGZIP() []byte { + file_cosmos_validate_module_v1_module_proto_rawDescOnce.Do(func() { + file_cosmos_validate_module_v1_module_proto_rawDescData = protoimpl.X.CompressGZIP(file_cosmos_validate_module_v1_module_proto_rawDescData) + }) + return file_cosmos_validate_module_v1_module_proto_rawDescData +} + +var file_cosmos_validate_module_v1_module_proto_msgTypes = make([]protoimpl.MessageInfo, 1) +var file_cosmos_validate_module_v1_module_proto_goTypes = []interface{}{ + (*Module)(nil), // 0: cosmos.validate.module.v1.Module +} +var file_cosmos_validate_module_v1_module_proto_depIdxs = []int32{ + 0, // [0:0] is the sub-list for method output_type + 0, // [0:0] is the sub-list for method input_type + 0, // [0:0] is the sub-list for extension type_name + 0, // [0:0] is the sub-list for extension extendee + 0, // [0:0] is the sub-list for field type_name +} + +func init() { file_cosmos_validate_module_v1_module_proto_init() } +func file_cosmos_validate_module_v1_module_proto_init() { + if File_cosmos_validate_module_v1_module_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_cosmos_validate_module_v1_module_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Module); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_cosmos_validate_module_v1_module_proto_rawDesc, + NumEnums: 0, + NumMessages: 1, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_cosmos_validate_module_v1_module_proto_goTypes, + DependencyIndexes: file_cosmos_validate_module_v1_module_proto_depIdxs, + MessageInfos: file_cosmos_validate_module_v1_module_proto_msgTypes, + }.Build() + File_cosmos_validate_module_v1_module_proto = out.File + file_cosmos_validate_module_v1_module_proto_rawDesc = nil + file_cosmos_validate_module_v1_module_proto_goTypes = nil + file_cosmos_validate_module_v1_module_proto_depIdxs = nil +} diff --git a/api/go.mod b/api/go.mod index 17e949d16f7a..c6e040103a8b 100644 --- a/api/go.mod +++ b/api/go.mod @@ -6,8 +6,8 @@ require ( buf.build/gen/go/cometbft/cometbft/protocolbuffers/go v1.34.2-20240701160653-fedbb9acfd2f.2 github.com/cosmos/cosmos-proto v1.0.0-beta.5 github.com/cosmos/gogoproto v1.7.0 - google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 - google.golang.org/grpc v1.66.2 + google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 + google.golang.org/grpc v1.67.1 google.golang.org/protobuf v1.34.2 ) @@ -17,5 +17,5 @@ require ( golang.org/x/net v0.29.0 // indirect golang.org/x/sys v0.25.0 // indirect golang.org/x/text v0.18.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f // indirect ) diff --git a/api/go.sum b/api/go.sum index f51fc49bc089..d1fd43b81060 100644 --- a/api/go.sum +++ b/api/go.sum @@ -16,11 +16,11 @@ golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= -google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 h1:+rdxYoE3E5htTEWIe15GlN6IfvbURM//Jt0mmkmm6ZU= -google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117/go.mod h1:OimBR/bc1wPO9iV4NC2bpyjy3VnAwZh5EBPQdtaE5oo= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:pPJltXNxVzT4pK9yD8vR9X75DaWYYmLGMsEvBfFQZzQ= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= -google.golang.org/grpc v1.66.2 h1:3QdXkuq3Bkh7w+ywLdLvM56cmGvQHUMZpiCzt6Rqaoo= -google.golang.org/grpc v1.66.2/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y= +google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 h1:wKguEg1hsxI2/L3hUYrpo1RVi48K+uTyzKqprwLXsb8= +google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142/go.mod h1:d6be+8HhtEtucleCbxpPW9PA9XwISACu8nvpPqF0BVo= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f h1:cUMEy+8oS78BWIH9OWazBkzbr090Od9tWBNtZHkOhf0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= +google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E= +google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= diff --git a/baseapp/abci.go b/baseapp/abci.go index 05b9e61794a7..dd091294d563 100644 --- a/baseapp/abci.go +++ b/baseapp/abci.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" "sort" + "strconv" "strings" "time" @@ -180,7 +181,8 @@ func (app *BaseApp) Query(_ context.Context, req *abci.QueryRequest) (resp *abci telemetry.IncrCounter(1, "query", "count") telemetry.IncrCounter(1, "query", req.Path) - defer telemetry.MeasureSince(telemetry.Now(), req.Path) + start := telemetry.Now() + defer telemetry.MeasureSince(start, req.Path) if req.Path == QueryPathBroadcastTx { return queryResult(errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "can't route a broadcast tx message"), app.trace), nil @@ -366,18 +368,27 @@ func (app *BaseApp) CheckTx(req *abci.CheckTxRequest) (*abci.CheckTxResponse, er return nil, fmt.Errorf("unknown RequestCheckTx type: %s", req.Type) } - gInfo, result, anteEvents, err := app.runTx(mode, req.Tx) - if err != nil { - return responseCheckTxWithEvents(err, gInfo.GasWanted, gInfo.GasUsed, anteEvents, app.trace), nil + if app.checkTxHandler == nil { + gInfo, result, anteEvents, err := app.runTx(mode, req.Tx, nil) + if err != nil { + return responseCheckTxWithEvents(err, gInfo.GasWanted, gInfo.GasUsed, anteEvents, app.trace), nil + } + + return &abci.CheckTxResponse{ + GasWanted: int64(gInfo.GasWanted), // TODO: Should type accept unsigned ints? + GasUsed: int64(gInfo.GasUsed), // TODO: Should type accept unsigned ints? + Log: result.Log, + Data: result.Data, + Events: sdk.MarkEventsToIndex(result.Events, app.indexEvents), + }, nil } - return &abci.CheckTxResponse{ - GasWanted: int64(gInfo.GasWanted), // TODO: Should type accept unsigned ints? - GasUsed: int64(gInfo.GasUsed), // TODO: Should type accept unsigned ints? - Log: result.Log, - Data: result.Data, - Events: sdk.MarkEventsToIndex(result.Events, app.indexEvents), - }, nil + // Create wrapper to avoid users overriding the execution mode + runTx := func(txBytes []byte, tx sdk.Tx) (gInfo sdk.GasInfo, result *sdk.Result, anteEvents []abci.Event, err error) { + return app.runTx(mode, txBytes, tx) + } + + return app.checkTxHandler(runTx, req) } // PrepareProposal implements the PrepareProposal ABCI method and returns a @@ -821,7 +832,7 @@ func (app *BaseApp) internalFinalizeBlock(ctx context.Context, req *abci.Finaliz // NOTE: Not all raw transactions may adhere to the sdk.Tx interface, e.g. // vote extensions, so skip those. txResults := make([]*abci.ExecTxResult, 0, len(req.Txs)) - for _, rawTx := range req.Txs { + for txIndex, rawTx := range req.Txs { response := app.deliverTx(rawTx) @@ -833,6 +844,12 @@ func (app *BaseApp) internalFinalizeBlock(ctx context.Context, req *abci.Finaliz // continue } + // append the tx index to the response.Events + for i, event := range response.Events { + response.Events[i].Attributes = append(event.Attributes, + abci.EventAttribute{Key: "tx_index", Value: strconv.Itoa(txIndex)}) + } + txResults = append(txResults, response) } diff --git a/baseapp/abci_test.go b/baseapp/abci_test.go index 07e7ea8199c9..111a86938356 100644 --- a/baseapp/abci_test.go +++ b/baseapp/abci_test.go @@ -676,7 +676,7 @@ func TestABCI_FinalizeBlock_DeliverTx(t *testing.T) { events := res.TxResults[i].GetEvents() require.Len(t, events, 3, "should contain ante handler, message type and counter events respectively") - require.Equal(t, sdk.MarkEventsToIndex(counterEvent("ante_handler", counter).ToABCIEvents(), map[string]struct{}{})[0], events[0], "ante handler event") + require.Equal(t, sdk.MarkEventsToIndex(counterEvent("ante_handler", counter).ToABCIEvents(), map[string]struct{}{})[0].Attributes[0], events[0].Attributes[0], "ante handler event") require.Equal(t, sdk.MarkEventsToIndex(counterEvent(sdk.EventTypeMessage, counter).ToABCIEvents(), map[string]struct{}{})[0].Attributes[0], events[2].Attributes[0], "msg handler update counter event") } @@ -1589,7 +1589,6 @@ func TestABCI_GetBlockRetentionHeight(t *testing.T) { } for name, tc := range testCases { - tc := tc tc.bapp.SetParamStore(¶mStore{db: coretesting.NewMemDB()}) _, err := tc.bapp.InitChain(&abci.InitChainRequest{ @@ -2081,7 +2080,7 @@ func TestABCI_PrepareProposal_VoteExtensions(t *testing.T) { return nil, err } - cp := ctx.ConsensusParams() // nolint:staticcheck // ignore linting error + cp := ctx.ConsensusParams() //nolint:staticcheck // ignore linting error extsEnabled := cp.Feature.VoteExtensionsEnableHeight != nil && req.Height >= cp.Feature.VoteExtensionsEnableHeight.Value && cp.Feature.VoteExtensionsEnableHeight.Value != 0 if !extsEnabled { // check abci params diff --git a/baseapp/abci_utils.go b/baseapp/abci_utils.go index 63c13fa8620b..bc0cb9daccdd 100644 --- a/baseapp/abci_utils.go +++ b/baseapp/abci_utils.go @@ -47,7 +47,7 @@ func ValidateVoteExtensions( extCommit abci.ExtendedCommitInfo, ) error { // Get values from context - cp := ctx.ConsensusParams() // nolint:staticcheck // ignore linting error + cp := ctx.ConsensusParams() //nolint:staticcheck // ignore linting error currentHeight := ctx.HeaderInfo().Height chainID := ctx.HeaderInfo().ChainID commitInfo := ctx.CometInfo().LastCommit @@ -258,25 +258,31 @@ func (h *DefaultProposalHandler) SetTxSelector(ts TxSelector) { func (h *DefaultProposalHandler) PrepareProposalHandler() sdk.PrepareProposalHandler { return func(ctx sdk.Context, req *abci.PrepareProposalRequest) (*abci.PrepareProposalResponse, error) { var maxBlockGas uint64 - if b := ctx.ConsensusParams().Block; b != nil { // nolint:staticcheck // ignore linting error + if b := ctx.ConsensusParams().Block; b != nil { //nolint:staticcheck // ignore linting error maxBlockGas = uint64(b.MaxGas) } defer h.txSelector.Clear() + // decode transactions + decodedTxs := make([]sdk.Tx, len(req.Txs)) + for i, txBz := range req.Txs { + tx, err := h.txVerifier.TxDecode(txBz) + if err != nil { + return nil, err + } + + decodedTxs[i] = tx + } + // If the mempool is nil or NoOp we simply return the transactions // requested from CometBFT, which, by default, should be in FIFO order. // // Note, we still need to ensure the transactions returned respect req.MaxTxBytes. _, isNoOp := h.mempool.(mempool.NoOpMempool) if h.mempool == nil || isNoOp { - for _, txBz := range req.Txs { - tx, err := h.txVerifier.TxDecode(txBz) - if err != nil { - return nil, err - } - - stop := h.txSelector.SelectTxForProposal(ctx, uint64(req.MaxTxBytes), maxBlockGas, tx, txBz) + for i, tx := range decodedTxs { + stop := h.txSelector.SelectTxForProposal(ctx, uint64(req.MaxTxBytes), maxBlockGas, tx, req.Txs[i]) if stop { break } @@ -291,7 +297,7 @@ func (h *DefaultProposalHandler) PrepareProposalHandler() sdk.PrepareProposalHan selectedTxsNums int invalidTxs []sdk.Tx // invalid txs to be removed out of the loop to avoid dead lock ) - h.mempool.SelectBy(ctx, req.Txs, func(memTx sdk.Tx) bool { + h.mempool.SelectBy(ctx, decodedTxs, func(memTx sdk.Tx) bool { unorderedTx, ok := memTx.(sdk.TxWithUnordered) isUnordered := ok && unorderedTx.GetUnordered() txSignersSeqs := make(map[string]uint64) @@ -405,7 +411,7 @@ func (h *DefaultProposalHandler) ProcessProposalHandler() sdk.ProcessProposalHan var totalTxGas uint64 var maxBlockGas int64 - if b := ctx.ConsensusParams().Block; b != nil { // nolint:staticcheck // ignore linting error + if b := ctx.ConsensusParams().Block; b != nil { //nolint:staticcheck // ignore linting error maxBlockGas = b.MaxGas } diff --git a/baseapp/abci_utils_test.go b/baseapp/abci_utils_test.go index 7dae39542c18..e2c88c2431b7 100644 --- a/baseapp/abci_utils_test.go +++ b/baseapp/abci_utils_test.go @@ -691,6 +691,7 @@ func (s *ABCIUtilsTestSuite) TestDefaultProposalHandler_PriorityNonceMempoolTxSe ph := baseapp.NewDefaultProposalHandler(mp, app) for _, v := range tc.txInputs { + app.EXPECT().TxDecode(v.bz).Return(v.tx, nil).AnyTimes() app.EXPECT().PrepareProposalVerifyTx(v.tx).Return(v.bz, nil).AnyTimes() s.NoError(mp.Insert(s.ctx.WithPriority(v.priority), v.tx)) tc.req.Txs = append(tc.req.Txs, v.bz) diff --git a/baseapp/baseapp.go b/baseapp/baseapp.go index 89748eadf053..2ef933c205c3 100644 --- a/baseapp/baseapp.go +++ b/baseapp/baseapp.go @@ -91,6 +91,7 @@ type BaseApp struct { prepareCheckStater sdk.PrepareCheckStater // logic to run during commit using the checkState precommiter sdk.Precommiter // logic to run during commit using the deliverState versionModifier server.VersionModifier // interface to get and set the app version + checkTxHandler sdk.CheckTxHandler addrPeerFilter sdk.PeerFilter // filter peers by address and port idPeerFilter sdk.PeerFilter // filter peers by node ID @@ -688,7 +689,6 @@ func (app *BaseApp) getContextForTx(mode execMode, txBytes []byte) sdk.Context { // a branched multi-store. func (app *BaseApp) cacheTxContext(ctx sdk.Context, txBytes []byte) (sdk.Context, storetypes.CacheMultiStore) { ms := ctx.MultiStore() - // TODO: https://github.com/cosmos/cosmos-sdk/issues/2824 msCache := ms.CacheMultiStore() if msCache.TracingEnabled() { msCache = msCache.SetTracingContext( @@ -718,6 +718,15 @@ func (app *BaseApp) preBlock(req *abci.FinalizeBlockRequest) ([]abci.Event, erro ctx = ctx.WithBlockGasMeter(gasMeter) app.finalizeBlockState.SetContext(ctx) events = ctx.EventManager().ABCIEvents() + + // append PreBlock attributes to all events + for i, event := range events { + events[i].Attributes = append( + event.Attributes, + abci.EventAttribute{Key: "mode", Value: "PreBlock"}, + abci.EventAttribute{Key: "event_index", Value: strconv.Itoa(i)}, + ) + } } return events, nil } @@ -739,6 +748,7 @@ func (app *BaseApp) beginBlock(_ *abci.FinalizeBlockRequest) (sdk.BeginBlock, er resp.Events[i].Attributes = append( event.Attributes, abci.EventAttribute{Key: "mode", Value: "BeginBlock"}, + abci.EventAttribute{Key: "event_index", Value: strconv.Itoa(i)}, ) } @@ -761,7 +771,7 @@ func (app *BaseApp) deliverTx(tx []byte) *abci.ExecTxResult { telemetry.SetGauge(float32(gInfo.GasWanted), "tx", "gas", "wanted") }() - gInfo, result, anteEvents, err := app.runTx(execModeFinalize, tx) + gInfo, result, anteEvents, err := app.runTx(execModeFinalize, tx, nil) if err != nil { resultStr = "failed" resp = responseExecTxResultWithEvents( @@ -801,6 +811,7 @@ func (app *BaseApp) endBlock(_ context.Context) (sdk.EndBlock, error) { eb.Events[i].Attributes = append( event.Attributes, abci.EventAttribute{Key: "mode", Value: "EndBlock"}, + abci.EventAttribute{Key: "event_index", Value: strconv.Itoa(i)}, ) } @@ -822,7 +833,9 @@ type HasNestedMsgs interface { // Note, gas execution info is always returned. A reference to a Result is // returned if the tx does not run out of gas and if all the messages are valid // and execute successfully. An error is returned otherwise. -func (app *BaseApp) runTx(mode execMode, txBytes []byte) (gInfo sdk.GasInfo, result *sdk.Result, anteEvents []abci.Event, err error) { +// both txbytes and the decoded tx are passed to runTx to avoid the state machine encoding the tx and decoding the transaction twice +// passing the decoded tx to runTX is optional, it will be decoded if the tx is nil +func (app *BaseApp) runTx(mode execMode, txBytes []byte, tx sdk.Tx) (gInfo sdk.GasInfo, result *sdk.Result, anteEvents []abci.Event, err error) { // NOTE: GasWanted should be returned by the AnteHandler. GasUsed is // determined by the GasMeter. We need access to the context to get the gas // meter, so we initialize upfront. @@ -870,9 +883,12 @@ func (app *BaseApp) runTx(mode execMode, txBytes []byte) (gInfo sdk.GasInfo, res defer consumeBlockGas() } - tx, err := app.txDecoder(txBytes) - if err != nil { - return sdk.GasInfo{GasUsed: 0, GasWanted: 0}, nil, nil, sdkerrors.ErrTxDecode.Wrap(err.Error()) + // if the transaction is not decoded, decode it here + if tx == nil { + tx, err = app.txDecoder(txBytes) + if err != nil { + return sdk.GasInfo{GasUsed: 0, GasWanted: 0}, nil, nil, sdkerrors.ErrTxDecode.Wrap(err.Error()) + } } msgs := tx.GetMsgs() @@ -1146,6 +1162,12 @@ func createEvents(cdc codec.Codec, events sdk.Events, msg sdk.Msg, reflectMsg pr } } + // append the event_index attribute to all events + msgEvent = msgEvent.AppendAttributes(sdk.NewAttribute("event_index", "0")) + for i, event := range events { + events[i] = event.AppendAttributes(sdk.NewAttribute("event_index", strconv.Itoa(i+1))) + } + return sdk.Events{msgEvent}.AppendEvents(events), nil } @@ -1160,7 +1182,7 @@ func (app *BaseApp) PrepareProposalVerifyTx(tx sdk.Tx) ([]byte, error) { return nil, err } - _, _, _, err = app.runTx(execModePrepareProposal, bz) + _, _, _, err = app.runTx(execModePrepareProposal, bz, tx) if err != nil { return nil, err } @@ -1179,7 +1201,7 @@ func (app *BaseApp) ProcessProposalVerifyTx(txBz []byte) (sdk.Tx, error) { return nil, err } - _, _, _, err = app.runTx(execModeProcessProposal, txBz) + _, _, _, err = app.runTx(execModeProcessProposal, txBz, tx) if err != nil { return nil, err } diff --git a/baseapp/internal/protocompat/protocompat.go b/baseapp/internal/protocompat/protocompat.go index bd277e4a44f7..004efe635e2a 100644 --- a/baseapp/internal/protocompat/protocompat.go +++ b/baseapp/internal/protocompat/protocompat.go @@ -6,7 +6,7 @@ import ( "reflect" gogoproto "github.com/cosmos/gogoproto/proto" - "github.com/golang/protobuf/proto" // nolint: staticcheck // needed because gogoproto.Merge does not work consistently. See NOTE: comments. + "github.com/golang/protobuf/proto" //nolint: staticcheck // needed because gogoproto.Merge does not work consistently. See NOTE: comments. "google.golang.org/grpc" proto2 "google.golang.org/protobuf/proto" "google.golang.org/protobuf/reflect/protoreflect" diff --git a/baseapp/options.go b/baseapp/options.go index 53286b2540b9..743d04c5543c 100644 --- a/baseapp/options.go +++ b/baseapp/options.go @@ -367,6 +367,15 @@ func (app *BaseApp) SetPrepareProposal(handler sdk.PrepareProposalHandler) { app.prepareProposal = handler } +// SetCheckTxHandler sets the checkTx function for the BaseApp. +func (app *BaseApp) SetCheckTxHandler(handler sdk.CheckTxHandler) { + if app.sealed { + panic("SetCheckTx() on sealed BaseApp") + } + + app.checkTxHandler = handler +} + func (app *BaseApp) SetExtendVoteHandler(handler sdk.ExtendVoteHandler) { if app.sealed { panic("SetExtendVoteHandler() on sealed BaseApp") diff --git a/baseapp/snapshot_test.go b/baseapp/snapshot_test.go index e6e6f1e5bd7d..e19b9cdfa9f5 100644 --- a/baseapp/snapshot_test.go +++ b/baseapp/snapshot_test.go @@ -245,7 +245,6 @@ func TestABCI_OfferSnapshot_Errors(t *testing.T) { }, abci.OFFER_SNAPSHOT_RESULT_REJECT}, } for name, tc := range testCases { - tc := tc t.Run(name, func(t *testing.T) { resp, err := suite.baseApp.OfferSnapshot(&abci.OfferSnapshotRequest{Snapshot: tc.snapshot}) require.NoError(t, err) diff --git a/baseapp/streaming.go b/baseapp/streaming.go index 6eeb8e37b449..3e30f8888d58 100644 --- a/baseapp/streaming.go +++ b/baseapp/streaming.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "sort" + "strconv" "strings" abci "github.com/cometbft/cometbft/api/cometbft/abci/v1" @@ -33,7 +34,7 @@ const ( // kv-store keys, and app modules. Using the built-in indexer framework is mutually exclusive from using other // types of streaming listeners. func (app *BaseApp) EnableIndexer(indexerOpts interface{}, keys map[string]*storetypes.KVStoreKey, appModules map[string]any) error { - listener, err := indexer.StartManager(indexer.ManagerOptions{ + listener, err := indexer.StartIndexing(indexer.IndexingOptions{ Config: indexerOpts, Resolver: decoding.ModuleSetDecoderResolver(appModules), SyncSource: nil, @@ -47,7 +48,7 @@ func (app *BaseApp) EnableIndexer(indexerOpts interface{}, keys map[string]*stor app.cms.AddListeners(exposedKeys) app.streamingManager = storetypes.StreamingManager{ - ABCIListeners: []storetypes.ABCIListener{listenerWrapper{listener}}, + ABCIListeners: []storetypes.ABCIListener{listenerWrapper{listener.Listener}}, StopNodeOnErr: true, } @@ -143,21 +144,111 @@ func exposeStoreKeysSorted(keysStr []string, keys map[string]*storetypes.KVStore return exposeStoreKeys } +func eventToAppDataEvent(event abci.Event) (appdata.Event, error) { + appdataEvent := appdata.Event{ + Type: event.Type, + Attributes: func() ([]appdata.EventAttribute, error) { + attrs := make([]appdata.EventAttribute, len(event.Attributes)) + for j, attr := range event.Attributes { + attrs[j] = appdata.EventAttribute{ + Key: attr.Key, + Value: attr.Value, + } + } + return attrs, nil + }, + } + + for _, attr := range event.Attributes { + if attr.Key == "mode" { + switch attr.Value { + case "PreBlock": + appdataEvent.BlockStage = appdata.PreBlockStage + case "BeginBlock": + appdataEvent.BlockStage = appdata.BeginBlockStage + case "EndBlock": + appdataEvent.BlockStage = appdata.EndBlockStage + default: + appdataEvent.BlockStage = appdata.UnknownBlockStage + } + } else if attr.Key == "tx_index" { + txIndex, err := strconv.Atoi(attr.Value) + if err != nil { + return appdata.Event{}, err + } + appdataEvent.TxIndex = int32(txIndex + 1) + appdataEvent.BlockStage = appdata.TxProcessingStage + } else if attr.Key == "msg_index" { + msgIndex, err := strconv.Atoi(attr.Value) + if err != nil { + return appdata.Event{}, err + } + appdataEvent.MsgIndex = int32(msgIndex + 1) + } else if attr.Key == "event_index" { + eventIndex, err := strconv.Atoi(attr.Value) + if err != nil { + return appdata.Event{}, err + } + appdataEvent.EventIndex = int32(eventIndex + 1) + } + } + + return appdataEvent, nil +} + type listenerWrapper struct { listener appdata.Listener } +// NewListenerWrapper creates a new listenerWrapper. +// It is only used for testing purposes. +func NewListenerWrapper(listener appdata.Listener) listenerWrapper { + return listenerWrapper{listener: listener} +} + func (p listenerWrapper) ListenFinalizeBlock(_ context.Context, req abci.FinalizeBlockRequest, res abci.FinalizeBlockResponse) error { if p.listener.StartBlock != nil { - err := p.listener.StartBlock(appdata.StartBlockData{ - Height: uint64(req.Height), - }) - if err != nil { + if err := p.listener.StartBlock(appdata.StartBlockData{ + Height: uint64(req.Height), + HeaderBytes: nil, // TODO: https://github.com/cosmos/cosmos-sdk/issues/22009 + HeaderJSON: nil, // TODO: https://github.com/cosmos/cosmos-sdk/issues/22009 + }); err != nil { + return err + } + } + if p.listener.OnTx != nil { + for i, tx := range req.Txs { + if err := p.listener.OnTx(appdata.TxData{ + TxIndex: int32(i), + Bytes: func() ([]byte, error) { return tx, nil }, + JSON: nil, // TODO: https://github.com/cosmos/cosmos-sdk/issues/22009 + }); err != nil { + return err + } + } + } + if p.listener.OnEvent != nil { + events := make([]appdata.Event, len(res.Events)) + var err error + for i, event := range res.Events { + events[i], err = eventToAppDataEvent(event) + if err != nil { + return err + } + } + for _, txResult := range res.TxResults { + for _, event := range txResult.Events { + appdataEvent, err := eventToAppDataEvent(event) + if err != nil { + return err + } + events = append(events, appdataEvent) + } + } + if err := p.listener.OnEvent(appdata.EventData{Events: events}); err != nil { return err } } - - //// TODO txs, events return nil } diff --git a/baseapp/streaming_test.go b/baseapp/streaming_test.go index b0779c6b91ca..cb3c065be31f 100644 --- a/baseapp/streaming_test.go +++ b/baseapp/streaming_test.go @@ -9,10 +9,12 @@ import ( tmproto "github.com/cometbft/cometbft/api/cometbft/types/v1" "github.com/stretchr/testify/require" + "cosmossdk.io/schema/appdata" storetypes "cosmossdk.io/store/types" "github.com/cosmos/cosmos-sdk/baseapp" baseapptestutil "github.com/cosmos/cosmos-sdk/baseapp/testutil" + sdk "github.com/cosmos/cosmos-sdk/types" ) var _ storetypes.ABCIListener = (*MockABCIListener)(nil) @@ -146,3 +148,186 @@ func Test_Ctx_with_StreamingManager(t *testing.T) { require.NoError(t, err) } } + +type mockAppDataListener struct { + appdata.Listener + + startBlockData []appdata.StartBlockData + txData []appdata.TxData + eventData []appdata.EventData + kvPairData []appdata.KVPairData + commitData []appdata.CommitData +} + +func newMockAppDataListener() *mockAppDataListener { + listener := &mockAppDataListener{} + + // Initialize the Listener with custom behavior to store data + listener.Listener = appdata.Listener{ + StartBlock: func(data appdata.StartBlockData) error { + listener.startBlockData = append(listener.startBlockData, data) // Store StartBlockData + return nil + }, + OnTx: func(data appdata.TxData) error { + listener.txData = append(listener.txData, data) // Store TxData + return nil + }, + OnEvent: func(data appdata.EventData) error { + listener.eventData = append(listener.eventData, data) // Store EventData + return nil + }, + OnKVPair: func(data appdata.KVPairData) error { + listener.kvPairData = append(listener.kvPairData, data) // Store KVPairData + return nil + }, + Commit: func(data appdata.CommitData) (func() error, error) { + listener.commitData = append(listener.commitData, data) // Store CommitData + return nil, nil + }, + } + + return listener +} + +func TestAppDataListener(t *testing.T) { + anteKey := []byte("ante-key") + anteOpt := func(bapp *baseapp.BaseApp) { bapp.SetAnteHandler(anteHandlerTxTest(t, capKey1, anteKey)) } + distOpt := func(bapp *baseapp.BaseApp) { bapp.MountStores(distKey1) } + mockListener := newMockAppDataListener() + streamingManager := storetypes.StreamingManager{ABCIListeners: []storetypes.ABCIListener{baseapp.NewListenerWrapper(mockListener.Listener)}} + streamingManagerOpt := func(bapp *baseapp.BaseApp) { bapp.SetStreamingManager(streamingManager) } + addListenerOpt := func(bapp *baseapp.BaseApp) { bapp.CommitMultiStore().AddListeners([]storetypes.StoreKey{distKey1}) } + + // for event tests + baseappOpts := func(app *baseapp.BaseApp) { + app.SetPreBlocker(func(ctx sdk.Context, req *abci.FinalizeBlockRequest) error { + ctx.EventManager().EmitEvent(sdk.NewEvent("pre-block")) + return nil + }) + app.SetBeginBlocker(func(_ sdk.Context) (sdk.BeginBlock, error) { + return sdk.BeginBlock{ + Events: []abci.Event{ + {Type: "begin-block"}, + }, + }, nil + }) + app.SetEndBlocker(func(_ sdk.Context) (sdk.EndBlock, error) { + return sdk.EndBlock{ + Events: []abci.Event{ + {Type: "end-block"}, + }, + }, nil + }) + } + + suite := NewBaseAppSuite(t, anteOpt, distOpt, streamingManagerOpt, addListenerOpt, baseappOpts) + + _, err := suite.baseApp.InitChain( + &abci.InitChainRequest{ + ConsensusParams: &tmproto.ConsensusParams{}, + }, + ) + require.NoError(t, err) + deliverKey := []byte("deliver-key") + baseapptestutil.RegisterCounterServer(suite.baseApp.MsgServiceRouter(), CounterServerImpl{t, capKey1, deliverKey}) + + txCount := 5 + txs := make([][]byte, txCount) + + for i := 0; i < txCount; i++ { + tx := newTxCounter(t, suite.txConfig, suite.ac, int64(i), int64(i)) + + txBytes, err := suite.txConfig.TxEncoder()(tx) + require.NoError(t, err) + + sKey := []byte(fmt.Sprintf("distKey%d", i)) + sVal := []byte(fmt.Sprintf("distVal%d", i)) + store := getFinalizeBlockStateCtx(suite.baseApp).KVStore(distKey1) + store.Set(sKey, sVal) + + txs[i] = txBytes + } + + _, err = suite.baseApp.FinalizeBlock(&abci.FinalizeBlockRequest{Height: 1, Txs: txs}) + require.NoError(t, err) + _, err = suite.baseApp.Commit() + require.NoError(t, err) + + // StartBlockData + require.Len(t, mockListener.startBlockData, 1) + require.Equal(t, uint64(1), mockListener.startBlockData[0].Height) + // TxData + txData := mockListener.txData + require.Len(t, txData, len(txs)) + for i := 0; i < txCount; i++ { + require.Equal(t, int32(i), txData[i].TxIndex) + txBytes, err := txData[i].Bytes() + require.NoError(t, err) + require.Equal(t, txs[i], txBytes) + } + // KVPairData + require.Len(t, mockListener.kvPairData, 1) + updates := mockListener.kvPairData[0].Updates + for i := 0; i < txCount; i++ { + require.Equal(t, []byte(distKey1.Name()), updates[i].Actor) + require.Len(t, updates[i].StateChanges, 1) + sKey := []byte(fmt.Sprintf("distKey%d", i)) + sVal := []byte(fmt.Sprintf("distVal%d", i)) + require.Equal(t, sKey, updates[i].StateChanges[0].Key) + require.Equal(t, sVal, updates[i].StateChanges[0].Value) + } + // CommitData + require.Len(t, mockListener.commitData, 1) + // EventData + require.Len(t, mockListener.eventData, 1) + events := mockListener.eventData[0].Events + require.Len(t, events, 3+txCount*3) + + for i := 0; i < 3; i++ { + require.Equal(t, int32(0), events[i].TxIndex) + require.Equal(t, int32(0), events[i].MsgIndex) + require.Equal(t, int32(1), events[i].EventIndex) + attrs, err := events[i].Attributes() + require.NoError(t, err) + require.Len(t, attrs, 2) + switch i { + case 0: + require.Equal(t, appdata.PreBlockStage, events[i].BlockStage) + require.Equal(t, "pre-block", events[i].Type) + case 1: + require.Equal(t, appdata.BeginBlockStage, events[i].BlockStage) + require.Equal(t, "begin-block", events[i].Type) + case 2: + require.Equal(t, appdata.EndBlockStage, events[i].BlockStage) + require.Equal(t, "end-block", events[i].Type) + } + } + + for i := 3; i < 3+txCount*3; i++ { + require.Equal(t, appdata.TxProcessingStage, events[i].BlockStage) + require.Equal(t, int32(i/3), events[i].TxIndex) + switch i % 3 { + case 0: + require.Equal(t, "ante_handler", events[i].Type) + require.Equal(t, int32(0), events[i].MsgIndex) + require.Equal(t, int32(0), events[i].EventIndex) + attrs, err := events[i].Attributes() + require.NoError(t, err) + require.Len(t, attrs, 2) + case 1: + require.Equal(t, "message", events[i].Type) + require.Equal(t, int32(1), events[i].MsgIndex) + require.Equal(t, int32(1), events[i].EventIndex) + attrs, err := events[i].Attributes() + require.NoError(t, err) + require.Len(t, attrs, 5) + case 2: + require.Equal(t, "message", events[i].Type) + require.Equal(t, int32(1), events[i].MsgIndex) + require.Equal(t, int32(2), events[i].EventIndex) + attrs, err := events[i].Attributes() + require.NoError(t, err) + require.Len(t, attrs, 4) + } + } +} diff --git a/baseapp/test_helpers.go b/baseapp/test_helpers.go index fcd0e55c8447..7cae8e541b7d 100644 --- a/baseapp/test_helpers.go +++ b/baseapp/test_helpers.go @@ -19,13 +19,13 @@ func (app *BaseApp) SimCheck(txEncoder sdk.TxEncoder, tx sdk.Tx) (sdk.GasInfo, * return sdk.GasInfo{}, nil, errorsmod.Wrapf(sdkerrors.ErrInvalidRequest, "%s", err) } - gasInfo, result, _, err := app.runTx(execModeCheck, bz) + gasInfo, result, _, err := app.runTx(execModeCheck, bz, tx) return gasInfo, result, err } // Simulate executes a tx in simulate mode to get result and gas info. func (app *BaseApp) Simulate(txBytes []byte) (sdk.GasInfo, *sdk.Result, error) { - gasInfo, result, _, err := app.runTx(execModeSimulate, txBytes) + gasInfo, result, _, err := app.runTx(execModeSimulate, txBytes, nil) return gasInfo, result, err } @@ -36,7 +36,7 @@ func (app *BaseApp) SimDeliver(txEncoder sdk.TxEncoder, tx sdk.Tx) (sdk.GasInfo, return sdk.GasInfo{}, nil, errorsmod.Wrapf(sdkerrors.ErrInvalidRequest, "%s", err) } - gasInfo, result, _, err := app.runTx(execModeFinalize, bz) + gasInfo, result, _, err := app.runTx(execModeFinalize, bz, tx) return gasInfo, result, err } diff --git a/buf.work.yaml b/buf.work.yaml index 5a070acabfd2..afd7c4ea0d8e 100644 --- a/buf.work.yaml +++ b/buf.work.yaml @@ -2,7 +2,6 @@ version: v1 directories: - proto - x/accounts/proto - - x/auth/proto - x/authz/proto - x/bank/proto - x/circuit/proto diff --git a/client/cmd_test.go b/client/cmd_test.go index 559d31d39f40..31c7bf390b01 100644 --- a/client/cmd_test.go +++ b/client/cmd_test.go @@ -125,8 +125,6 @@ func TestSetCmdClientContextHandler(t *testing.T) { } for _, tc := range testCases { - tc := tc - t.Run(tc.name, func(t *testing.T) { cmd := newCmd() _ = testutil.ApplyMockIODiscardOutErr(cmd) diff --git a/client/config/config_test.go b/client/config/config_test.go index 248ed47cea9c..81fe9e9f56a1 100644 --- a/client/config/config_test.go +++ b/client/config/config_test.go @@ -145,7 +145,6 @@ func TestConfigCmdEnvFlag(t *testing.T) { } for _, tc := range tt { - tc := tc t.Run(tc.name, func(t *testing.T) { testCmd := &cobra.Command{ Use: "test", diff --git a/client/flags/flags_test.go b/client/flags/flags_test.go index 5cc591bebbe7..657de9c0e658 100644 --- a/client/flags/flags_test.go +++ b/client/flags/flags_test.go @@ -22,8 +22,6 @@ func TestParseGasSetting(t *testing.T) { } for _, tc := range testCases { - tc := tc - t.Run(tc.name, func(t *testing.T) { gs, err := flags.ParseGasSetting(tc.input) diff --git a/client/grpc/cmtservice/status_test.go b/client/grpc/cmtservice/status_test.go index 9f7ab9567921..d7bfa6bdc192 100644 --- a/client/grpc/cmtservice/status_test.go +++ b/client/grpc/cmtservice/status_test.go @@ -14,7 +14,7 @@ import ( ) func TestStatusCommand(t *testing.T) { - t.Skip() // https://github.com/cosmos/cosmos-sdk/issues/17446 + t.Skip() // Rewrite as system test cfg, err := network.DefaultConfigWithAppConfig(depinject.Configs() /* TODO, test skipped anyway */) require.NoError(t, err) diff --git a/client/keys/add_ledger_test.go b/client/keys/add_ledger_test.go index 3d04cc5e3b92..d130127614f9 100644 --- a/client/keys/add_ledger_test.go +++ b/client/keys/add_ledger_test.go @@ -172,7 +172,6 @@ func Test_runAddCmdLedgerDryRun(t *testing.T) { } for _, tt := range testData { - tt := tt t.Run(tt.name, func(t *testing.T) { cmd := AddKeyCommand() cmd.Flags().AddFlagSet(Commands().PersistentFlags()) diff --git a/client/keys/add_test.go b/client/keys/add_test.go index 687aff609235..703bc5894c18 100644 --- a/client/keys/add_test.go +++ b/client/keys/add_test.go @@ -297,7 +297,6 @@ func Test_runAddCmdDryRun(t *testing.T) { }, } for _, tt := range testData { - tt := tt t.Run(tt.name, func(t *testing.T) { cmd := AddKeyCommand() cmd.Flags().AddFlagSet(Commands().PersistentFlags()) diff --git a/client/keys/import.go b/client/keys/import.go index 9a86da287978..c9893239ae07 100644 --- a/client/keys/import.go +++ b/client/keys/import.go @@ -34,7 +34,7 @@ func ImportKeyCommand() *cobra.Command { } buf := bufio.NewReader(clientCtx.Input) - bz, err := os.ReadFile(args[1]) + armor, err := os.ReadFile(args[1]) if err != nil { return err } @@ -44,17 +44,17 @@ func ImportKeyCommand() *cobra.Command { return err } - return clientCtx.Keyring.ImportPrivKey(args[0], string(bz), passphrase) + return clientCtx.Keyring.ImportPrivKey(name, string(armor), passphrase) }, } } func ImportKeyHexCommand() *cobra.Command { cmd := &cobra.Command{ - Use: "import-hex ", + Use: "import-hex [hex]", Short: "Import private keys into the local keybase", Long: fmt.Sprintf("Import hex encoded private key into the local keybase.\nSupported key-types can be obtained with:\n%s list-key-types", version.AppName), - Args: cobra.ExactArgs(2), + Args: cobra.RangeArgs(1, 2), RunE: func(cmd *cobra.Command, args []string) error { clientCtx, err := client.GetClientQueryContext(cmd) if err != nil { @@ -65,7 +65,17 @@ func ImportKeyHexCommand() *cobra.Command { return errors.New("the provided name is invalid or empty after trimming whitespace") } keyType, _ := cmd.Flags().GetString(flags.FlagKeyType) - return clientCtx.Keyring.ImportPrivKeyHex(args[0], args[1], keyType) + var hexKey string + if len(args) == 2 { + hexKey = args[1] + } else { + buf := bufio.NewReader(clientCtx.Input) + hexKey, err = input.GetPassword("Enter hex private key:", buf) + if err != nil { + return err + } + } + return clientCtx.Keyring.ImportPrivKeyHex(name, hexKey, keyType) }, } cmd.Flags().String(flags.FlagKeyType, string(hd.Secp256k1Type), "private key signing algorithm kind") diff --git a/client/keys/import_test.go b/client/keys/import_test.go index bc9c5d34abb7..3f73cbd9659f 100644 --- a/client/keys/import_test.go +++ b/client/keys/import_test.go @@ -82,11 +82,11 @@ HbP+c6JmeJy9JXe2rbbF1QtCX1gLqGcDQPBXiCtFvP7/8wTZtVOPj8vREzhZ9ElO // Now add a temporary keybase kbHome := filepath.Join(t.TempDir(), fmt.Sprintf("kbhome-%s", tc.name)) - // Create dir, otherwise os.WriteFile will fail - if _, err := os.Stat(kbHome); os.IsNotExist(err) { - err = os.MkdirAll(kbHome, 0o700) - require.NoError(t, err) - } + require.NoError(t, os.MkdirAll(kbHome, 0o700)) + t.Cleanup(func() { + require.NoError(t, os.RemoveAll(kbHome)) + }) + kb, err := keyring.New(sdk.KeyringServiceName(), tc.keyringBackend, kbHome, nil, cdc) require.NoError(t, err) @@ -97,15 +97,9 @@ HbP+c6JmeJy9JXe2rbbF1QtCX1gLqGcDQPBXiCtFvP7/8wTZtVOPj8vREzhZ9ElO WithCodec(cdc) ctx := context.WithValue(context.Background(), client.ClientContextKey, &clientCtx) - t.Cleanup(cleanupKeys(t, kb, "keyname1")) - keyfile := filepath.Join(kbHome, "key.asc") require.NoError(t, os.WriteFile(keyfile, []byte(armoredKey), 0o600)) - defer func() { - _ = os.RemoveAll(kbHome) - }() - mockIn.Reset(tc.userInput) cmd.SetArgs([]string{ "keyname1", keyfile, @@ -128,6 +122,7 @@ func Test_runImportHexCmd(t *testing.T) { name string keyringBackend string hexKey string + stdInput bool keyType string expectError bool }{ @@ -137,6 +132,13 @@ func Test_runImportHexCmd(t *testing.T) { hexKey: "0xa3e57952e835ed30eea86a2993ac2a61c03e74f2085b3635bd94aa4d7ae0cfdf", keyType: "secp256k1", }, + { + name: "read the hex key from standard input", + keyringBackend: keyring.BackendTest, + stdInput: true, + hexKey: "0xa3e57952e835ed30eea86a2993ac2a61c03e74f2085b3635bd94aa4d7ae0cfdf", + keyType: "secp256k1", + }, } for _, tc := range testCases { @@ -147,6 +149,10 @@ func Test_runImportHexCmd(t *testing.T) { // Now add a temporary keybase kbHome := filepath.Join(t.TempDir(), fmt.Sprintf("kbhome-%s", tc.name)) + t.Cleanup(func() { + require.NoError(t, os.RemoveAll(kbHome)) + }) + kb, err := keyring.New(sdk.KeyringServiceName(), tc.keyringBackend, kbHome, nil, cdc) require.NoError(t, err) @@ -157,17 +163,17 @@ func Test_runImportHexCmd(t *testing.T) { WithCodec(cdc) ctx := context.WithValue(context.Background(), client.ClientContextKey, &clientCtx) - t.Cleanup(cleanupKeys(t, kb, "keyname1")) - - defer func() { - _ = os.RemoveAll(kbHome) - }() - - cmd.SetArgs([]string{ - "keyname1", tc.hexKey, + args := []string{"keyname1"} + if tc.stdInput { + mockIn.Reset(tc.hexKey) + } else { + args = append(args, tc.hexKey) + } + cmd.SetArgs(append( + args, fmt.Sprintf("--%s=%s", flags.FlagKeyType, tc.keyType), fmt.Sprintf("--%s=%s", flags.FlagKeyringBackend, tc.keyringBackend), - }) + )) err = cmd.ExecuteContext(ctx) if tc.expectError { diff --git a/client/keys/list_test.go b/client/keys/list_test.go index 8f2752e5af9f..8660c0fe17d0 100644 --- a/client/keys/list_test.go +++ b/client/keys/list_test.go @@ -67,7 +67,6 @@ func Test_runListCmd(t *testing.T) { {"keybase: w/key", kbHome2, false}, } for _, tt := range testData { - tt := tt t.Run(tt.name, func(t *testing.T) { cmd.SetArgs([]string{ fmt.Sprintf("--%s=%s", flags.FlagKeyringDir, tt.kbDir), diff --git a/client/keys/migrate.go b/client/keys/migrate.go index 0a9fc78e2143..b2e192dffb93 100644 --- a/client/keys/migrate.go +++ b/client/keys/migrate.go @@ -18,8 +18,6 @@ Otherwise, we try to deserialize it using Amino into LegacyInfo. If this attempt LegacyInfo to Protobuf serialization format and overwrite the keyring entry. If any error occurred, it will be outputted in CLI and migration will be continued until all keys in the keyring DB are exhausted. See https://github.com/cosmos/cosmos-sdk/pull/9695 for more details. - -It is recommended to run in 'dry-run' mode first to verify all key migration material. `, Args: cobra.NoArgs, RunE: runMigrateCmd, diff --git a/client/keys/parse_test.go b/client/keys/parse_test.go index 650cb7c501f0..88c9c31ec5e6 100644 --- a/client/keys/parse_test.go +++ b/client/keys/parse_test.go @@ -21,7 +21,6 @@ func TestParseKey(t *testing.T) { {"hex", []string{hexstr}, false}, } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { require.Equal(t, tt.wantErr, doParseKey(ParseKeyStringCommand(), "cosmos", tt.args) != nil) }) diff --git a/client/keys/show_test.go b/client/keys/show_test.go index 2f75430638a6..f309ad73b195 100644 --- a/client/keys/show_test.go +++ b/client/keys/show_test.go @@ -237,7 +237,6 @@ func Test_validateMultisigThreshold(t *testing.T) { {"1-2", args{2, 1}, true}, } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { if err := validateMultisigThreshold(tt.args.k, tt.args.nKeys); (err != nil) != tt.wantErr { t.Errorf("validateMultisigThreshold() error = %v, wantErr %v", err, tt.wantErr) @@ -272,7 +271,6 @@ func Test_getBechKeyOut(t *testing.T) { {"cons", args{sdk.PrefixConsensus}, MkConsKeyOutput, false}, } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { output, err := getKeyOutput(ctx, tt.args.bechPrefix, k) if tt.wantErr { diff --git a/client/tx/aux_builder_test.go b/client/tx/aux_builder_test.go index f2083846ce38..6380f2d6ee50 100644 --- a/client/tx/aux_builder_test.go +++ b/client/tx/aux_builder_test.go @@ -214,7 +214,6 @@ func TestAuxTxBuilder(t *testing.T) { } for _, tc := range testcases { - tc := tc t.Run(tc.name, func(t *testing.T) { b = tx.NewAuxTxBuilder() err := tc.malleate() diff --git a/client/tx/tx_test.go b/client/tx/tx_test.go index 2669fe804983..21bfff6070b8 100644 --- a/client/tx/tx_test.go +++ b/client/tx/tx_test.go @@ -81,7 +81,6 @@ func TestCalculateGas(t *testing.T) { } for _, tc := range testCases { - stc := tc txCfg, _ := newTestTxConfig() defaultSignMode, err := signing.APISignModeToInternal(txCfg.SignModeHandler().DefaultMode()) require.NoError(t, err) @@ -90,16 +89,16 @@ func TestCalculateGas(t *testing.T) { WithChainID("test-chain"). WithTxConfig(txCfg).WithSignMode(defaultSignMode) - t.Run(stc.name, func(t *testing.T) { + t.Run(tc.name, func(t *testing.T) { mockClientCtx := mockContext{ gasUsed: tc.args.mockGasUsed, wantErr: tc.args.mockWantErr, } - simRes, gotAdjusted, err := CalculateGas(mockClientCtx, txf.WithGasAdjustment(stc.args.adjustment)) - if stc.expPass { + simRes, gotAdjusted, err := CalculateGas(mockClientCtx, txf.WithGasAdjustment(tc.args.adjustment)) + if tc.expPass { require.NoError(t, err) - require.Equal(t, simRes.GasInfo.GasUsed, stc.wantEstimate) - require.Equal(t, gotAdjusted, stc.wantAdjusted) + require.Equal(t, simRes.GasInfo.GasUsed, tc.wantEstimate) + require.Equal(t, gotAdjusted, tc.wantAdjusted) require.NotNil(t, simRes.Result) } else { require.Error(t, err) diff --git a/client/utils_test.go b/client/utils_test.go index c8cb93a9f56d..61bfb429cc3b 100644 --- a/client/utils_test.go +++ b/client/utils_test.go @@ -67,7 +67,6 @@ func TestPaginate(t *testing.T) { } for i, tc := range testCases { - i, tc := i, tc t.Run(tc.name, func(t *testing.T) { start, end := client.Paginate(tc.numObjs, tc.page, tc.limit, tc.defLimit) require.Equal(t, tc.expectedStart, start, "invalid result; test case #%d", i) diff --git a/client/v2/CHANGELOG.md b/client/v2/CHANGELOG.md index 5fae2c385bdc..a3702845c575 100644 --- a/client/v2/CHANGELOG.md +++ b/client/v2/CHANGELOG.md @@ -42,11 +42,25 @@ Ref: https://keepachangelog.com/en/1.0.0/ * [#18626](https://github.com/cosmos/cosmos-sdk/pull/18626) Support for off-chain signing and verification of a file. * [#18461](https://github.com/cosmos/cosmos-sdk/pull/18461) Support governance proposals. +* [#20623](https://github.com/cosmos/cosmos-sdk/pull/20623) Introduce client/v2 tx factory. +* [#20623](https://github.com/cosmos/cosmos-sdk/pull/20623) Extend client/v2 keyring interface with `KeyType` and `KeyInfo`. + +### Improvements + +* [#21936](https://github.com/cosmos/cosmos-sdk/pull/21936) Print possible enum values in error message after an invalid input was provided. ### API Breaking Changes * [#17709](https://github.com/cosmos/cosmos-sdk/pull/17709) Address codecs have been removed from `autocli.AppOptions` and `flag.Builder`. Instead client/v2 uses the address codecs present in the context (introduced in [#17503](https://github.com/cosmos/cosmos-sdk/pull/17503)). +## [v2.0.0-beta.5] - 2024-09-18 + +### Improvements + +* [#21712](https://github.com/cosmos/cosmos-sdk/pull/21712) Marshal `type` field as proto message url in queries instead of amino name. + +## [v2.0.0-beta.4] - 2024-07-16 + ### Bug Fixes * [#20964](https://github.com/cosmos/cosmos-sdk/pull/20964) Fix `GetNodeHomeDirectory` helper in `client/v2/helpers` to respect the `(PREFIX)_HOME` environment variable. diff --git a/client/v2/README.md b/client/v2/README.md index 9efc241748af..b4c2666850ee 100644 --- a/client/v2/README.md +++ b/client/v2/README.md @@ -2,7 +2,9 @@ sidebar_position: 1 --- -# AutoCLI +# Client/v2 + +## AutoCLI :::note Synopsis This document details how to build CLI and REST interfaces for a module. Examples from various Cosmos SDK modules are included. @@ -14,9 +16,9 @@ This document details how to build CLI and REST interfaces for a module. Example ::: -The `autocli` (also known as `client/v2`) package is a [Go library](https://pkg.go.dev/cosmossdk.io/client/v2/autocli) for generating CLI (command line interface) interfaces for Cosmos SDK-based applications. It provides a simple way to add CLI commands to your application by generating them automatically based on your gRPC service definitions. Autocli generates CLI commands and flags directly from your protobuf messages, including options, input parameters, and output parameters. This means that you can easily add a CLI interface to your application without having to manually create and manage commands. +The `autocli` (also known as `client/v2/autocli`) package is a [Go library](https://pkg.go.dev/cosmossdk.io/client/v2/autocli) for generating CLI (command line interface) interfaces for Cosmos SDK-based applications. It provides a simple way to add CLI commands to your application by generating them automatically based on your gRPC service definitions. Autocli generates CLI commands and flags directly from your protobuf messages, including options, input parameters, and output parameters. This means that you can easily add a CLI interface to your application without having to manually create and manage commands. -## Overview +### Overview `autocli` generates CLI commands and flags for each method defined in your gRPC service. By default, it generates commands for each gRPC services. The commands are named based on the name of the service method. @@ -32,7 +34,7 @@ For instance, `autocli` would generate a command named `my-method` for the `MyMe It is possible to customize the generation of transactions and queries by defining options for each service. -## Application Wiring +### Application Wiring Here are the steps to use AutoCLI: @@ -73,7 +75,7 @@ if err := rootCmd.Execute(); err != nil { } ``` -### Keyring +#### Keyring `autocli` uses a keyring for key name resolving names and signing transactions. @@ -100,7 +102,7 @@ keyring.NewAutoCLIKeyring(kb) ::: -## Signing +### Signing `autocli` supports signing transactions with the keyring. The [`cosmos.msg.v1.signer` protobuf annotation](https://docs.cosmos.network/main/build/building-modules/protobuf-annotations) defines the signer field of the message. @@ -110,7 +112,7 @@ This field is automatically filled when using the `--from` flag or defining the AutoCLI currently supports only one signer per transaction. ::: -## Module wiring & Customization +### Module wiring & Customization The `AutoCLIOptions()` method on your module allows to specify custom commands, sub-commands or flags for each service, as it was a `cobra.Command` instance, within the `RpcCommandOptions` struct. Defining such options will customize the behavior of the `autocli` command generation, which by default generates a command for each method in your gRPC service. @@ -131,31 +133,7 @@ AutoCLI can create a gov proposal of any tx by simply setting the `GovProposal` Users can however use the `--no-proposal` flag to disable the proposal creation (which is useful if the authority isn't the gov module on a chain). ::: -### Conventions for the `Use` field in Cobra - -According to the [Cobra documentation](https://pkg.go.dev/github.com/spf13/cobra#Command) the following conventions should be followed for the `Use` field in Cobra commands: - -1. **Required arguments**: - * Should not be enclosed in brackets. They can be enclosed in angle brackets `< >` for clarity. - * Example: `command ` - -2. **Optional arguments**: - * Should be enclosed in square brackets `[ ]`. - * Example: `command [optional_argument]` - -3. **Alternative (mutually exclusive) arguments**: - * Should be enclosed in curly braces `{ }`. - * Example: `command {-a | -b}` for required alternatives. - * Example: `command [-a | -b]` for optional alternatives. - -4. **Multiple arguments**: - * Indicated with `...` after the argument. - * Example: `command argument...` - -5. **Combination of options**: - * Example: `command [-F file | -D dir]... [-f format] profile` - -### Specifying Subcommands +#### Specifying Subcommands By default, `autocli` generates a command for each method in your gRPC service. However, you can specify subcommands to group related commands together. To specify subcommands, use the `autocliv1.ServiceCommandDescriptor` struct. @@ -165,7 +143,7 @@ This example shows how to use the `autocliv1.ServiceCommandDescriptor` struct to https://github.com/cosmos/cosmos-sdk/blob/v0.50.0-beta.0/x/gov/autocli.go#L94-L97 ``` -### Positional Arguments +#### Positional Arguments By default `autocli` generates a flag for each field in your protobuf message. However, you can choose to use positional arguments instead of flags for certain fields. @@ -183,7 +161,7 @@ Then the command can be used as follows, instead of having to specify the `--add query auth account cosmos1abcd...xyz ``` -### Customising Flag Names +#### Customising Flag Names By default, `autocli` generates flag names based on the names of the fields in your protobuf message. However, you can customise the flag names by providing a `FlagOptions`. This parameter allows you to specify custom names for flags based on the names of the message fields. @@ -200,7 +178,7 @@ autocliv1.RpcCommandOptions{ `FlagsOptions` is defined like sub commands in the `AutoCLIOptions()` method on your module. -### Combining AutoCLI with Other Commands Within A Module +#### Combining AutoCLI with Other Commands Within A Module AutoCLI can be used alongside other commands within a module. For example, the `gov` module uses AutoCLI to generate commands for the `query` subcommand, but also defines custom commands for the `proposer` subcommands. @@ -212,7 +190,7 @@ https://github.com/cosmos/cosmos-sdk/blob/fa4d87ef7e6d87aaccc94c337ffd2fe90fcb7a If not set to true, `AutoCLI` will not generate commands for the module if there are already commands registered for the module (when `GetTxCmd()` or `GetQueryCmd()` are defined). -### Skip a command +#### Skip a command AutoCLI automatically skips unsupported commands when [`cosmos_proto.method_added_in` protobuf annotation](https://docs.cosmos.network/main/build/building-modules/protobuf-annotations) is present. @@ -225,7 +203,7 @@ Additionally, a command can be manually skipped using the `autocliv1.RpcCommandO } ``` -### Use AutoCLI for non module commands +#### Use AutoCLI for non module commands It is possible to use `AutoCLI` for non module commands. The trick is still to implement the `appmodule.Module` interface and append it to the `appOptions.ModuleOptions` map. @@ -235,17 +213,41 @@ For example, here is how the SDK does it for `cometbft` gRPC commands: https://github.com/cosmos/cosmos-sdk/blob/main/client/grpc/cmtservice/autocli.go#L52-L71 ``` -## Summary +#### Conventions for the `Use` field in Cobra + +According to the [Cobra documentation](https://pkg.go.dev/github.com/spf13/cobra#Command) the following conventions should be followed for the `Use` field in Cobra commands: + +1. **Required arguments**: + * Should not be enclosed in brackets. They can be enclosed in angle brackets `< >` for clarity. + * Example: `command ` + +2. **Optional arguments**: + * Should be enclosed in square brackets `[ ]`. + * Example: `command [optional_argument]` + +3. **Alternative (mutually exclusive) arguments**: + * Should be enclosed in curly braces `{ }`. + * Example: `command {-a | -b}` for required alternatives. + * Example: `command [-a | -b]` for optional alternatives. + +4. **Multiple arguments**: + * Indicated with `...` after the argument. + * Example: `command argument...` + +5. **Combination of options**: + * Example: `command [-F file | -D dir]... [-f format] profile` + +### Summary `autocli` lets you generate CLI to your Cosmos SDK-based applications without any cobra boilerplate. It allows you to easily generate CLI commands and flags from your protobuf messages, and provides many options for customising the behavior of your CLI application. To further enhance your CLI experience with Cosmos SDK-based blockchains, you can use `hubl`. `hubl` is a tool that allows you to query any Cosmos SDK-based blockchain using the new AutoCLI feature of the Cosmos SDK. With `hubl`, you can easily configure a new chain and query modules with just a few simple commands. -For more information on `hubl`, including how to configure a new chain and query a module, see the [Hubl documentation](https://docs.cosmos.network/main/tooling/hubl). +For more information on `hubl`, including how to configure a new chain and query a module, see the [Hubl documentation](https://docs.cosmos.network/main/build/tooling/hubl). # Off-Chain -Off-chain functionalities allow you to sign and verify files with two commands: +Off-chain is a `client/v2` package providing functionalities for allowing to sign and verify files with two commands: * `sign-file` for signing a file. * `verify-file` for verifying a previously signed file. @@ -275,6 +277,7 @@ The `encoding` flag lets you choose how the contents of the file should be encod "signer": "cosmos1x33fy6rusfprkntvjsfregss7rvsvyy4lkwrqu", "data": "Hello World!\n" } + ``` * `simd off-chain sign-file alice myFile.json --encoding base64` @@ -286,6 +289,7 @@ The `encoding` flag lets you choose how the contents of the file should be encod "signer": "cosmos1x33fy6rusfprkntvjsfregss7rvsvyy4lkwrqu", "data": "SGVsbG8gV29ybGQhCg==" } + ``` * `simd off-chain sign-file alice myFile.json --encoding hex` diff --git a/client/v2/autocli/flag/address.go b/client/v2/autocli/flag/address.go index 58108d094990..454c30a317dd 100644 --- a/client/v2/autocli/flag/address.go +++ b/client/v2/autocli/flag/address.go @@ -151,7 +151,7 @@ func getKeyringFromCtx(ctx *context.Context) keyring.Keyring { dctx := *ctx if dctx != nil { if clientCtx := dctx.Value(client.ClientContextKey); clientCtx != nil { - k, err := sdkkeyring.NewAutoCLIKeyring(clientCtx.(*client.Context).Keyring) + k, err := sdkkeyring.NewAutoCLIKeyring(clientCtx.(*client.Context).Keyring, clientCtx.(*client.Context).AddressCodec) if err != nil { panic(fmt.Errorf("failed to create keyring: %w", err)) } diff --git a/client/v2/autocli/flag/enum.go b/client/v2/autocli/flag/enum.go index 72b27528a9a5..db3f57627511 100644 --- a/client/v2/autocli/flag/enum.go +++ b/client/v2/autocli/flag/enum.go @@ -58,7 +58,12 @@ func (e enumValue) String() string { func (e *enumValue) Set(s string) error { valDesc, ok := e.valMap[s] if !ok { - return fmt.Errorf("%s is not a valid value for enum %s", s, e.enum.FullName()) + var validValues []string + for k := range e.valMap { + validValues = append(validValues, k) + } + + return fmt.Errorf("%s is not a valid value for enum %s. Valid values are: %s", s, e.enum.FullName(), strings.Join(validValues, ", ")) } e.value = valDesc.Number() return nil diff --git a/client/v2/autocli/keyring/interface.go b/client/v2/autocli/keyring/interface.go index fa448bd20599..7f2fee1b3e3d 100644 --- a/client/v2/autocli/keyring/interface.go +++ b/client/v2/autocli/keyring/interface.go @@ -20,4 +20,10 @@ type Keyring interface { // Sign signs the given bytes with the key with the given name. Sign(name string, msg []byte, signMode signingv1beta1.SignMode) ([]byte, error) + + // KeyType returns the type of the key. + KeyType(name string) (uint, error) + + // KeyInfo given a key name or address returns key name, key address and key type. + KeyInfo(nameOrAddr string) (string, string, uint, error) } diff --git a/client/v2/autocli/keyring/keyring.go b/client/v2/autocli/keyring/keyring.go index 70c2d27d08ed..f5dce25efceb 100644 --- a/client/v2/autocli/keyring/keyring.go +++ b/client/v2/autocli/keyring/keyring.go @@ -48,3 +48,13 @@ func (k *KeyringImpl) LookupAddressByKeyName(name string) ([]byte, error) { func (k *KeyringImpl) Sign(name string, msg []byte, signMode signingv1beta1.SignMode) ([]byte, error) { return k.k.Sign(name, msg, signMode) } + +// KeyType returns the type of the key. +func (k *KeyringImpl) KeyType(name string) (uint, error) { + return k.k.KeyType(name) +} + +// KeyInfo given a key name or address returns key name, key address and key type. +func (k *KeyringImpl) KeyInfo(nameOrAddr string) (string, string, uint, error) { + return k.k.KeyInfo(nameOrAddr) +} diff --git a/client/v2/autocli/keyring/no_keyring.go b/client/v2/autocli/keyring/no_keyring.go index e14267cee5e3..7f0be9c7593e 100644 --- a/client/v2/autocli/keyring/no_keyring.go +++ b/client/v2/autocli/keyring/no_keyring.go @@ -29,3 +29,11 @@ func (k NoKeyring) GetPubKey(name string) (cryptotypes.PubKey, error) { func (k NoKeyring) Sign(name string, msg []byte, signMode signingv1beta1.SignMode) ([]byte, error) { return nil, errNoKeyring } + +func (k NoKeyring) KeyType(name string) (uint, error) { + return 0, errNoKeyring +} + +func (k NoKeyring) KeyInfo(name string) (string, string, uint, error) { + return "", "", 0, errNoKeyring +} diff --git a/client/v2/autocli/msg.go b/client/v2/autocli/msg.go index b19aabc95ba0..9eb4f0444bba 100644 --- a/client/v2/autocli/msg.go +++ b/client/v2/autocli/msg.go @@ -58,7 +58,9 @@ func (b *Builder) AddMsgServiceCommands(cmd *cobra.Command, cmdDescriptor *autoc return err } - cmd.AddCommand(subCmd) + if !subCmdDescriptor.EnhanceCustomCommand { + cmd.AddCommand(subCmd) + } } if cmdDescriptor.Service == "" { diff --git a/client/v2/autocli/query.go b/client/v2/autocli/query.go index dc268b573654..d308bcd7633a 100644 --- a/client/v2/autocli/query.go +++ b/client/v2/autocli/query.go @@ -53,7 +53,9 @@ func (b *Builder) AddQueryServiceCommands(cmd *cobra.Command, cmdDescriptor *aut return err } - cmd.AddCommand(subCmd) + if !subCmdDesc.EnhanceCustomCommand { + cmd.AddCommand(subCmd) + } } // skip empty command descriptors @@ -119,11 +121,12 @@ func (b *Builder) BuildQueryMethodCommand(ctx context.Context, descriptor protor methodName := fmt.Sprintf("/%s/%s", serviceDescriptor.FullName(), descriptor.Name()) outputType := util.ResolveMessageType(b.TypeResolver, descriptor.Output()) encoderOptions := aminojson.EncoderOptions{ - Indent: " ", - EnumAsString: true, - DoNotSortFields: true, - TypeResolver: b.TypeResolver, - FileResolver: b.FileResolver, + Indent: " ", + EnumAsString: true, + DoNotSortFields: true, + AminoNameAsTypeURL: true, + TypeResolver: b.TypeResolver, + FileResolver: b.FileResolver, } cmd, err := b.buildMethodCommandCommon(descriptor, options, func(cmd *cobra.Command, input protoreflect.Message) error { diff --git a/client/v2/autocli/query_test.go b/client/v2/autocli/query_test.go index f5db25c40b36..1cbca64fb951 100644 --- a/client/v2/autocli/query_test.go +++ b/client/v2/autocli/query_test.go @@ -575,8 +575,6 @@ func TestBinaryFlag(t *testing.T) { } func TestAddressValidation(t *testing.T) { - t.Skip() // TODO(@julienrbrt) re-able with better keyring instiantiation - fixture := initFixture(t) _, err := runCmd(fixture, buildModuleQueryCommand, diff --git a/client/v2/go.mod b/client/v2/go.mod index 64655bbfc946..b999f9c15ba5 100644 --- a/client/v2/go.mod +++ b/client/v2/go.mod @@ -3,8 +3,8 @@ module cosmossdk.io/client/v2 go 1.23.1 require ( - cosmossdk.io/api v0.7.5 - cosmossdk.io/core v1.0.0-alpha.2 + cosmossdk.io/api v0.7.6 + cosmossdk.io/core v1.0.0-alpha.4 cosmossdk.io/depinject v1.0.0 cosmossdk.io/x/bank v0.0.0-20240226161501-23359a0b6d91 cosmossdk.io/x/gov v0.0.0-20231113122742-912390d5fc4a @@ -13,7 +13,7 @@ require ( github.com/cosmos/cosmos-sdk v0.53.0 github.com/spf13/cobra v1.8.1 github.com/spf13/pflag v1.0.5 - google.golang.org/grpc v1.66.2 + google.golang.org/grpc v1.67.1 google.golang.org/protobuf v1.34.2 gotest.tools/v3 v3.5.1 sigs.k8s.io/yaml v1.4.0 @@ -23,10 +23,11 @@ require ( buf.build/gen/go/cometbft/cometbft/protocolbuffers/go v1.34.2-20240701160653-fedbb9acfd2f.2 // indirect buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.34.2-20240130113600-88ef6483f90f.2 // indirect cosmossdk.io/collections v0.4.0 // indirect + cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29 // indirect cosmossdk.io/errors v1.0.1 // indirect cosmossdk.io/log v1.4.1 // indirect cosmossdk.io/math v1.3.0 - cosmossdk.io/schema v0.2.0 // indirect + cosmossdk.io/schema v0.3.1-0.20240930054013-7c6e0388a3f9 // indirect cosmossdk.io/store v1.1.1-0.20240418092142-896cdf1971bc // indirect cosmossdk.io/x/staking v0.0.0-00010101000000-000000000000 // indirect filippo.io/edwards25519 v1.1.0 // indirect @@ -52,7 +53,7 @@ require ( github.com/cosmos/btcutil v1.0.5 // indirect github.com/cosmos/cosmos-db v1.0.3-0.20240911104526-ddc3f09bfc22 // indirect github.com/cosmos/crypto v0.1.2 // indirect - github.com/cosmos/go-bip39 v1.0.0 // indirect + github.com/cosmos/go-bip39 v1.0.0 github.com/cosmos/gogogateway v1.2.0 // indirect github.com/cosmos/gogoproto v1.7.0 github.com/cosmos/iavl v1.3.0 // indirect @@ -100,7 +101,7 @@ require ( github.com/hashicorp/hcl v1.0.0 // indirect github.com/hashicorp/yamux v0.1.1 // indirect github.com/hdevalence/ed25519consensus v0.2.0 // indirect - github.com/huandu/skiplist v1.2.0 // indirect + github.com/huandu/skiplist v1.2.1 // indirect github.com/iancoleman/strcase v0.3.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jmhodges/levigo v1.0.0 // indirect @@ -124,9 +125,9 @@ require ( github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/client_golang v1.20.3 // indirect + github.com/prometheus/client_golang v1.20.4 // indirect github.com/prometheus/client_model v0.6.1 // indirect - github.com/prometheus/common v0.59.1 // indirect + github.com/prometheus/common v0.60.0 // indirect github.com/prometheus/procfs v0.15.1 // indirect github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect github.com/rogpeppe/go-internal v1.12.0 // indirect @@ -162,21 +163,18 @@ require ( golang.org/x/text v0.18.0 // indirect golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect pgregory.net/rapid v1.1.0 // indirect ) -require cosmossdk.io/core/testing v0.0.0-00010101000000-000000000000 // indirect - replace github.com/cosmos/cosmos-sdk => ./../../ // TODO remove post spinning out all modules replace ( cosmossdk.io/api => ./../../api - cosmossdk.io/core/testing => ../../core/testing cosmossdk.io/store => ./../../store cosmossdk.io/x/bank => ./../../x/bank cosmossdk.io/x/gov => ./../../x/gov diff --git a/client/v2/go.sum b/client/v2/go.sum index 37704b3a32de..1a32ea6bc6f2 100644 --- a/client/v2/go.sum +++ b/client/v2/go.sum @@ -6,8 +6,10 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cosmossdk.io/collections v0.4.0 h1:PFmwj2W8szgpD5nOd8GWH6AbYNi1f2J6akWXJ7P5t9s= cosmossdk.io/collections v0.4.0/go.mod h1:oa5lUING2dP+gdDquow+QjlF45eL1t4TJDypgGd+tv0= -cosmossdk.io/core v1.0.0-alpha.2 h1:epU0Xwces4Rgl5bMhHHkXGaGDcyucNGlC/JDH+Suckg= -cosmossdk.io/core v1.0.0-alpha.2/go.mod h1:abgLjeFLhtuKIYZWSPlVUgQBrKObO7ULV35KYfexE90= +cosmossdk.io/core v1.0.0-alpha.4 h1:9iuroT9ejDYETCsGkzkvs/wAY/5UFl7nCIINFRxyMJY= +cosmossdk.io/core v1.0.0-alpha.4/go.mod h1:3u9cWq1FAVtiiCrDPpo4LhR+9V6k/ycSG4/Y/tREWCY= +cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29 h1:NxxUo0GMJUbIuVg0R70e3cbn9eFTEuMr7ev1AFvypdY= +cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29/go.mod h1:8s2tPeJtSiQuoyPmr2Ag7meikonISO4Fv4MoO8+ORrs= cosmossdk.io/depinject v1.0.0 h1:dQaTu6+O6askNXO06+jyeUAnF2/ssKwrrszP9t5q050= cosmossdk.io/depinject v1.0.0/go.mod h1:zxK/h3HgHoA/eJVtiSsoaRaRA2D5U4cJ5thIG4ssbB8= cosmossdk.io/errors v1.0.1 h1:bzu+Kcr0kS/1DuPBtUFdWjzLqyUuCiyHjyJB6srBV/0= @@ -16,8 +18,8 @@ cosmossdk.io/log v1.4.1 h1:wKdjfDRbDyZRuWa8M+9nuvpVYxrEOwbD/CA8hvhU8QM= cosmossdk.io/log v1.4.1/go.mod h1:k08v0Pyq+gCP6phvdI6RCGhLf/r425UT6Rk/m+o74rU= cosmossdk.io/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE= cosmossdk.io/math v1.3.0/go.mod h1:vnRTxewy+M7BtXBNFybkuhSH4WfedVAAnERHgVFhp3k= -cosmossdk.io/schema v0.2.0 h1:UH5CR1DqUq8yP+5Np8PbvG4YX0zAUsTN2Qk6yThmfMk= -cosmossdk.io/schema v0.2.0/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= +cosmossdk.io/schema v0.3.1-0.20240930054013-7c6e0388a3f9 h1:DmOoS/1PeY6Ih0hAVlJ69kLMUrLV+TCbfICrZtB1vdU= +cosmossdk.io/schema v0.3.1-0.20240930054013-7c6e0388a3f9/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= cosmossdk.io/x/protocolpool v0.0.0-20230925135524-a1bc045b3190 h1:XQJj9Dv9Gtze0l2TF79BU5lkP6MkUveTUuKICmxoz+o= cosmossdk.io/x/protocolpool v0.0.0-20230925135524-a1bc045b3190/go.mod h1:7WUGupOvmlHJoIMBz1JbObQxeo6/TDiuDBxmtod8HRg= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= @@ -300,8 +302,8 @@ github.com/hdevalence/ed25519consensus v0.2.0/go.mod h1:w3BHWjwJbFU29IRHL1Iqkw3s github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/huandu/go-assert v1.1.5 h1:fjemmA7sSfYHJD7CUqs9qTwwfdNAx7/j2/ZlHXzNB3c= github.com/huandu/go-assert v1.1.5/go.mod h1:yOLvuqZwmcHIC5rIzrBhT7D3Q9c3GFnd0JrPVhn/06U= -github.com/huandu/skiplist v1.2.0 h1:gox56QD77HzSC0w+Ws3MH3iie755GBJU1OER3h5VsYw= -github.com/huandu/skiplist v1.2.0/go.mod h1:7v3iFjLcSAzO4fN5B8dvebvo/qsfumiLiDXMrPiHF9w= +github.com/huandu/skiplist v1.2.1 h1:dTi93MgjwErA/8idWTzIw4Y1kZsMWx35fmI2c8Rij7w= +github.com/huandu/skiplist v1.2.1/go.mod h1:7v3iFjLcSAzO4fN5B8dvebvo/qsfumiLiDXMrPiHF9w= github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI= github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= @@ -412,8 +414,8 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= -github.com/prometheus/client_golang v1.20.3 h1:oPksm4K8B+Vt35tUhw6GbSNSgVlVSBH0qELP/7u83l4= -github.com/prometheus/client_golang v1.20.3/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_golang v1.20.4 h1:Tgh3Yr67PaOv/uTqloMsCEdeuFTatm5zIq5+qNN23vI= +github.com/prometheus/client_golang v1.20.4/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -422,8 +424,8 @@ github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= -github.com/prometheus/common v0.59.1 h1:LXb1quJHWm1P6wq/U824uxYi4Sg0oGvNeUm1z5dJoX0= -github.com/prometheus/common v0.59.1/go.mod h1:GpWM7dewqmVYcd7SmRaiWVe9SSqjf0UrwnYnpEZNuT0= +github.com/prometheus/common v0.60.0 h1:+V9PAREWNvJMAuJ1x1BaWl9dewMW4YrHZQbx0sJNllA= +github.com/prometheus/common v0.60.0/go.mod h1:h0LYf1R1deLSKtD4Vdg8gy4RuOvENW2J/h19V5NADQw= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/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= @@ -648,10 +650,10 @@ google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEY google.golang.org/genproto v0.0.0-20220314164441-57ef72a4c106/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E= google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de h1:F6qOa9AZTYJXOUEr4jDysRDLrm4PHePlge4v4TGAlxY= google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:VUhTRKeHn9wwcdrk73nvdC9gF178Tzhmt/qyaFcPLSo= -google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 h1:+rdxYoE3E5htTEWIe15GlN6IfvbURM//Jt0mmkmm6ZU= -google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117/go.mod h1:OimBR/bc1wPO9iV4NC2bpyjy3VnAwZh5EBPQdtaE5oo= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:pPJltXNxVzT4pK9yD8vR9X75DaWYYmLGMsEvBfFQZzQ= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= +google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 h1:wKguEg1hsxI2/L3hUYrpo1RVi48K+uTyzKqprwLXsb8= +google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142/go.mod h1:d6be+8HhtEtucleCbxpPW9PA9XwISACu8nvpPqF0BVo= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f h1:cUMEy+8oS78BWIH9OWazBkzbr090Od9tWBNtZHkOhf0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= @@ -662,8 +664,8 @@ google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= -google.golang.org/grpc v1.66.2 h1:3QdXkuq3Bkh7w+ywLdLvM56cmGvQHUMZpiCzt6Rqaoo= -google.golang.org/grpc v1.66.2/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y= +google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E= +google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= 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= diff --git a/client/v2/internal/account/retriever.go b/client/v2/internal/account/retriever.go new file mode 100644 index 000000000000..2cef69f92cf8 --- /dev/null +++ b/client/v2/internal/account/retriever.go @@ -0,0 +1,116 @@ +package account + +import ( + "context" + "fmt" + "strconv" + + gogogrpc "github.com/cosmos/gogoproto/grpc" + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/metadata" + "google.golang.org/grpc/status" + + "cosmossdk.io/core/address" + + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" + sdk "github.com/cosmos/cosmos-sdk/types" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" +) + +// GRPCBlockHeightHeader represents the gRPC header for block height. +const GRPCBlockHeightHeader = "x-cosmos-block-height" + +var _ AccountRetriever = accountRetriever{} + +// Account provides a read-only abstraction over the auth module's AccountI. +type Account interface { + GetAddress() sdk.AccAddress + GetPubKey() cryptotypes.PubKey // can return nil. + GetAccountNumber() uint64 + GetSequence() uint64 +} + +// AccountRetriever defines methods required to retrieve account details necessary for transaction signing. +type AccountRetriever interface { + GetAccount(context.Context, []byte) (Account, error) + GetAccountWithHeight(context.Context, []byte) (Account, int64, error) + EnsureExists(context.Context, []byte) error + GetAccountNumberSequence(context.Context, []byte) (accNum, accSeq uint64, err error) +} + +type accountRetriever struct { + ac address.Codec + conn gogogrpc.ClientConn + registry codectypes.InterfaceRegistry +} + +// NewAccountRetriever creates a new instance of accountRetriever. +func NewAccountRetriever(ac address.Codec, conn gogogrpc.ClientConn, registry codectypes.InterfaceRegistry) *accountRetriever { + return &accountRetriever{ + ac: ac, + conn: conn, + registry: registry, + } +} + +// GetAccount retrieves an account using its address. +func (a accountRetriever) GetAccount(ctx context.Context, addr []byte) (Account, error) { + acc, _, err := a.GetAccountWithHeight(ctx, addr) + return acc, err +} + +// GetAccountWithHeight retrieves an account and its associated block height using the account's address. +func (a accountRetriever) GetAccountWithHeight(ctx context.Context, addr []byte) (Account, int64, error) { + var header metadata.MD + qc := authtypes.NewQueryClient(a.conn) + + addrStr, err := a.ac.BytesToString(addr) + if err != nil { + return nil, 0, err + } + + res, err := qc.Account(ctx, &authtypes.QueryAccountRequest{Address: addrStr}, grpc.Header(&header)) + if err != nil { + return nil, 0, err + } + + blockHeight := header.Get(GRPCBlockHeightHeader) + if len(blockHeight) != 1 { + return nil, 0, fmt.Errorf("unexpected '%s' header length; got %d, expected 1", GRPCBlockHeightHeader, len(blockHeight)) + } + + nBlockHeight, err := strconv.Atoi(blockHeight[0]) + if err != nil { + return nil, 0, fmt.Errorf("failed to parse block height: %w", err) + } + + var acc Account + if err := a.registry.UnpackAny(res.Account, &acc); err != nil { + return nil, 0, err + } + + return acc, int64(nBlockHeight), nil +} + +// EnsureExists checks if an account exists using its address. +func (a accountRetriever) EnsureExists(ctx context.Context, addr []byte) error { + if _, err := a.GetAccount(ctx, addr); err != nil { + return err + } + return nil +} + +// GetAccountNumberSequence retrieves the account number and sequence for an account using its address. +func (a accountRetriever) GetAccountNumberSequence(ctx context.Context, addr []byte) (accNum, accSeq uint64, err error) { + acc, err := a.GetAccount(ctx, addr) + if err != nil { + if status.Code(err) == codes.NotFound { + return 0, 0, nil + } + return 0, 0, err + } + + return acc.GetAccountNumber(), acc.GetSequence(), nil +} diff --git a/client/v2/internal/coins/util.go b/client/v2/internal/coins/util.go new file mode 100644 index 000000000000..1495386713f6 --- /dev/null +++ b/client/v2/internal/coins/util.go @@ -0,0 +1,66 @@ +package coins + +import ( + "errors" + + base "cosmossdk.io/api/cosmos/base/v1beta1" + "cosmossdk.io/math" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +var ( + _ withAmount = &base.Coin{} + _ withAmount = &base.DecCoin{} +) + +type withAmount interface { + GetAmount() string +} + +// IsZero check if given coins are zero. +func IsZero[T withAmount](coins []T) (bool, error) { + for _, coin := range coins { + amount, ok := math.NewIntFromString(coin.GetAmount()) + if !ok { + return false, errors.New("invalid coin amount") + } + if !amount.IsZero() { + return false, nil + } + } + return true, nil +} + +func ParseDecCoins(coins string) ([]*base.DecCoin, error) { + parsedGasPrices, err := sdk.ParseDecCoins(coins) // TODO: do it here to avoid sdk dependency + if err != nil { + return nil, err + } + + finalGasPrices := make([]*base.DecCoin, len(parsedGasPrices)) + for i, coin := range parsedGasPrices { + finalGasPrices[i] = &base.DecCoin{ + Denom: coin.Denom, + Amount: coin.Amount.String(), + } + } + return finalGasPrices, nil +} + +func ParseCoinsNormalized(coins string) ([]*base.Coin, error) { + parsedFees, err := sdk.ParseCoinsNormalized(coins) // TODO: do it here to avoid sdk dependency + if err != nil { + return nil, err + } + + finalFees := make([]*base.Coin, len(parsedFees)) + for i, coin := range parsedFees { + finalFees[i] = &base.Coin{ + Denom: coin.Denom, + Amount: coin.Amount.String(), + } + } + + return finalFees, nil +} diff --git a/client/v2/internal/coins/util_test.go b/client/v2/internal/coins/util_test.go new file mode 100644 index 000000000000..1ee7f5842920 --- /dev/null +++ b/client/v2/internal/coins/util_test.go @@ -0,0 +1,83 @@ +package coins + +import ( + "testing" + + "github.com/stretchr/testify/require" + + base "cosmossdk.io/api/cosmos/base/v1beta1" +) + +func TestCoinIsZero(t *testing.T) { + type testCase[T withAmount] struct { + name string + coins []T + isZero bool + } + tests := []testCase[*base.Coin]{ + { + name: "not zero coin", + coins: []*base.Coin{ + { + Denom: "stake", + Amount: "100", + }, + }, + isZero: false, + }, + { + name: "zero coin", + coins: []*base.Coin{ + { + Denom: "stake", + Amount: "0", + }, + }, + isZero: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := IsZero(tt.coins) + require.NoError(t, err) + require.Equal(t, got, tt.isZero) + }) + } +} + +func TestDecCoinIsZero(t *testing.T) { + type testCase[T withAmount] struct { + name string + coins []T + isZero bool + } + tests := []testCase[*base.DecCoin]{ + { + name: "not zero coin", + coins: []*base.DecCoin{ + { + Denom: "stake", + Amount: "100", + }, + }, + isZero: false, + }, + { + name: "zero coin", + coins: []*base.DecCoin{ + { + Denom: "stake", + Amount: "0", + }, + }, + isZero: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := IsZero(tt.coins) + require.NoError(t, err) + require.Equal(t, got, tt.isZero) + }) + } +} diff --git a/client/v2/offchain/sign.go b/client/v2/offchain/sign.go index fd01227ed13e..b36a50c00ca0 100644 --- a/client/v2/offchain/sign.go +++ b/client/v2/offchain/sign.go @@ -63,7 +63,7 @@ func Sign(ctx client.Context, rawBytes []byte, fromName, indent, encoding, outpu // sign signs a digest with provided key and SignMode. func sign(ctx client.Context, fromName, digest string) (*apitx.Tx, error) { - keybase, err := keyring.NewAutoCLIKeyring(ctx.Keyring) + keybase, err := keyring.NewAutoCLIKeyring(ctx.Keyring, ctx.AddressCodec) if err != nil { return nil, err } diff --git a/client/v2/tx/README.md b/client/v2/tx/README.md new file mode 100644 index 000000000000..ffe2fb8fda00 --- /dev/null +++ b/client/v2/tx/README.md @@ -0,0 +1,465 @@ +The tx package provides a robust set of tools for building, signing, and managing transactions in a Cosmos SDK-based blockchain application. + +## Overview + +This package includes several key components: + +1. Transaction Factory +2. Transaction Config +3. Transaction Encoder/Decoder +4. Signature Handling + +## Architecture + +```mermaid +graph TD + A[Client] --> B[Factory] + B --> D[TxConfig] + D --> E[TxEncodingConfig] + D --> F[TxSigningConfig] + B --> G[Tx] + G --> H[Encoder] + G --> I[Decoder] + F --> J[SignModeHandler] + F --> K[SigningContext] + B --> L[AuxTxBuilder] +``` + +## Key Components + +### TxConfig + +`TxConfig` provides configuration for transaction handling, including: + +- Encoding and decoding +- Sign mode handling +- Signature JSON marshaling/unmarshaling + +```mermaid +classDiagram + class TxConfig { + <> + TxEncodingConfig + TxSigningConfig + } + + class TxEncodingConfig { + <> + TxEncoder() txEncoder + TxDecoder() txDecoder + TxJSONEncoder() txEncoder + TxJSONDecoder() txDecoder + Decoder() Decoder + } + + class TxSigningConfig { + <> + SignModeHandler() *signing.HandlerMap + SigningContext() *signing.Context + MarshalSignatureJSON([]Signature) ([]byte, error) + UnmarshalSignatureJSON([]byte) ([]Signature, error) + } + + class txConfig { + TxEncodingConfig + TxSigningConfig + } + + class defaultEncodingConfig { + cdc codec.BinaryCodec + decoder Decoder + TxEncoder() txEncoder + TxDecoder() txDecoder + TxJSONEncoder() txEncoder + TxJSONDecoder() txDecoder + } + + class defaultTxSigningConfig { + signingCtx *signing.Context + handlerMap *signing.HandlerMap + cdc codec.BinaryCodec + SignModeHandler() *signing.HandlerMap + SigningContext() *signing.Context + MarshalSignatureJSON([]Signature) ([]byte, error) + UnmarshalSignatureJSON([]byte) ([]Signature, error) + } + + TxConfig <|-- txConfig + TxEncodingConfig <|.. defaultEncodingConfig + TxSigningConfig <|.. defaultTxSigningConfig + txConfig *-- defaultEncodingConfig + txConfig *-- defaultTxSigningConfig +``` + +### Factory + +The `Factory` is the main entry point for creating and managing transactions. It handles: + +- Account preparation +- Gas calculation +- Unsigned transaction building +- Transaction signing +- Transaction simulation +- Transaction broadcasting + +```mermaid +classDiagram + class Factory { + keybase keyring.Keyring + cdc codec.BinaryCodec + accountRetriever account.AccountRetriever + ac address.Codec + conn gogogrpc.ClientConn + txConfig TxConfig + txParams TxParameters + tx txState + + NewFactory(keybase, cdc, accRetriever, txConfig, ac, conn, parameters) Factory + Prepare() error + BuildUnsignedTx(msgs ...transaction.Msg) error + BuildsSignedTx(ctx context.Context, msgs ...transaction.Msg) (Tx, error) + calculateGas(msgs ...transaction.Msg) error + Simulate(msgs ...transaction.Msg) (*apitx.SimulateResponse, uint64, error) + UnsignedTxString(msgs ...transaction.Msg) (string, error) + BuildSimTx(msgs ...transaction.Msg) ([]byte, error) + sign(ctx context.Context, overwriteSig bool) (Tx, error) + WithGas(gas uint64) + WithSequence(sequence uint64) + WithAccountNumber(accnum uint64) + getTx() (Tx, error) + getFee() (*apitx.Fee, error) + getSigningTxData() (signing.TxData, error) + setSignatures(...Signature) error + } + + class TxParameters { + <> + chainID string + AccountConfig + GasConfig + FeeConfig + SignModeConfig + TimeoutConfig + MemoConfig + } + + class TxConfig { + <> + } + + class Tx { + <> + } + + class txState { + <> + msgs []transaction.Msg + memo string + fees []*base.Coin + gasLimit uint64 + feeGranter []byte + feePayer []byte + timeoutHeight uint64 + unordered bool + timeoutTimestamp uint64 + signatures []Signature + signerInfos []*apitx.SignerInfo + } + + Factory *-- TxParameters + Factory *-- TxConfig + Factory *-- txState + Factory ..> Tx : creates +``` + +### Encoder/Decoder + +The package includes functions for encoding and decoding transactions in both binary and JSON formats. + +```mermaid +classDiagram + class Decoder { + <> + Decode(txBytes []byte) (*txdecode.DecodedTx, error) + } + + class txDecoder { + <> + decode(txBytes []byte) (Tx, error) + } + + class txEncoder { + <> + encode(tx Tx) ([]byte, error) + } + + class EncoderUtils { + <> + decodeTx(cdc codec.BinaryCodec, decoder Decoder) txDecoder + encodeTx(tx Tx) ([]byte, error) + decodeJsonTx(cdc codec.BinaryCodec, decoder Decoder) txDecoder + encodeJsonTx(tx Tx) ([]byte, error) + protoTxBytes(tx *txv1beta1.Tx) ([]byte, error) + } + + class MarshalOptions { + <> + Deterministic bool + } + + class JSONMarshalOptions { + <> + Indent string + UseProtoNames bool + UseEnumNumbers bool + } + + Decoder <.. EncoderUtils : uses + txDecoder <.. EncoderUtils : creates + txEncoder <.. EncoderUtils : implements + EncoderUtils ..> MarshalOptions : uses + EncoderUtils ..> JSONMarshalOptions : uses +``` + +### Sequence Diagrams + +#### Generate Aux Signer Data +```mermaid +sequenceDiagram + participant User + participant GenerateOrBroadcastTxCLI + participant generateAuxSignerData + participant makeAuxSignerData + participant AuxTxBuilder + participant ctx.PrintProto + + User->>GenerateOrBroadcastTxCLI: Call with isAux flag + GenerateOrBroadcastTxCLI->>generateAuxSignerData: Call + + generateAuxSignerData->>makeAuxSignerData: Call + makeAuxSignerData->>AuxTxBuilder: NewAuxTxBuilder() + + makeAuxSignerData->>AuxTxBuilder: SetAddress(f.txParams.fromAddress) + + alt f.txParams.offline + makeAuxSignerData->>AuxTxBuilder: SetAccountNumber(f.AccountNumber()) + makeAuxSignerData->>AuxTxBuilder: SetSequence(f.Sequence()) + else + makeAuxSignerData->>f.accountRetriever: GetAccountNumberSequence() + makeAuxSignerData->>AuxTxBuilder: SetAccountNumber(accNum) + makeAuxSignerData->>AuxTxBuilder: SetSequence(seq) + end + + makeAuxSignerData->>AuxTxBuilder: SetMsgs(msgs...) + makeAuxSignerData->>AuxTxBuilder: SetSignMode(f.SignMode()) + + makeAuxSignerData->>f.keybase: GetPubKey(f.txParams.fromName) + makeAuxSignerData->>AuxTxBuilder: SetPubKey(pubKey) + + makeAuxSignerData->>AuxTxBuilder: SetChainID(f.txParams.chainID) + makeAuxSignerData->>AuxTxBuilder: GetSignBytes() + + makeAuxSignerData->>f.keybase: Sign(f.txParams.fromName, signBz, f.SignMode()) + makeAuxSignerData->>AuxTxBuilder: SetSignature(sig) + + makeAuxSignerData->>AuxTxBuilder: GetAuxSignerData() + AuxTxBuilder-->>makeAuxSignerData: Return AuxSignerData + makeAuxSignerData-->>generateAuxSignerData: Return AuxSignerData + + generateAuxSignerData->>ctx.PrintProto: Print AuxSignerData + ctx.PrintProto-->>GenerateOrBroadcastTxCLI: Return result + GenerateOrBroadcastTxCLI-->>User: Return result +``` + +#### Generate Only +```mermaid +sequenceDiagram + participant User + participant GenerateOrBroadcastTxCLI + participant generateOnly + participant Factory + participant ctx.PrintString + + User->>GenerateOrBroadcastTxCLI: Call with generateOnly flag + GenerateOrBroadcastTxCLI->>generateOnly: Call + + generateOnly->>Factory: Prepare() + alt Error in Prepare + Factory-->>generateOnly: Return error + generateOnly-->>GenerateOrBroadcastTxCLI: Return error + GenerateOrBroadcastTxCLI-->>User: Return error + end + + generateOnly->>Factory: UnsignedTxString(msgs...) + Factory->>Factory: BuildUnsignedTx(msgs...) + Factory->>Factory: setMsgs(msgs...) + Factory->>Factory: setMemo(f.txParams.memo) + Factory->>Factory: setFees(f.txParams.gasPrices) + Factory->>Factory: setGasLimit(f.txParams.gas) + Factory->>Factory: setFeeGranter(f.txParams.feeGranter) + Factory->>Factory: setFeePayer(f.txParams.feePayer) + Factory->>Factory: setTimeoutHeight(f.txParams.timeoutHeight) + + Factory->>Factory: getTx() + Factory->>Factory: txConfig.TxJSONEncoder() + Factory->>Factory: encoder(tx) + + Factory-->>generateOnly: Return unsigned tx string + generateOnly->>ctx.PrintString: Print unsigned tx string + ctx.PrintString-->>generateOnly: Return result + generateOnly-->>GenerateOrBroadcastTxCLI: Return result + GenerateOrBroadcastTxCLI-->>User: Return result +``` + +#### DryRun +```mermaid +sequenceDiagram + participant User + participant GenerateOrBroadcastTxCLI + participant dryRun + participant Factory + participant os.Stderr + + User->>GenerateOrBroadcastTxCLI: Call with dryRun flag + GenerateOrBroadcastTxCLI->>dryRun: Call + + dryRun->>Factory: Prepare() + alt Error in Prepare + Factory-->>dryRun: Return error + dryRun-->>GenerateOrBroadcastTxCLI: Return error + GenerateOrBroadcastTxCLI-->>User: Return error + end + + dryRun->>Factory: Simulate(msgs...) + Factory->>Factory: BuildSimTx(msgs...) + Factory->>Factory: BuildUnsignedTx(msgs...) + Factory->>Factory: getSimPK() + Factory->>Factory: getSimSignatureData(pk) + Factory->>Factory: setSignatures(sig) + Factory->>Factory: getTx() + Factory->>Factory: txConfig.TxEncoder()(tx) + + Factory->>ServiceClient: Simulate(context.Background(), &apitx.SimulateRequest{}) + ServiceClient->>Factory: Return result + + Factory-->>dryRun: Return (simulation, gas, error) + alt Error in Simulate + dryRun-->>GenerateOrBroadcastTxCLI: Return error + GenerateOrBroadcastTxCLI-->>User: Return error + end + + dryRun->>os.Stderr: Fprintf(GasEstimateResponse{GasEstimate: gas}) + os.Stderr-->>dryRun: Return result + dryRun-->>GenerateOrBroadcastTxCLI: Return result + GenerateOrBroadcastTxCLI-->>User: Return result +``` + +#### Generate and Broadcast Tx +```mermaid +sequenceDiagram + participant User + participant GenerateOrBroadcastTxCLI + participant BroadcastTx + participant Factory + participant clientCtx + + User->>GenerateOrBroadcastTxCLI: Call + GenerateOrBroadcastTxCLI->>BroadcastTx: Call + + BroadcastTx->>Factory: Prepare() + alt Error in Prepare + Factory-->>BroadcastTx: Return error + BroadcastTx-->>GenerateOrBroadcastTxCLI: Return error + GenerateOrBroadcastTxCLI-->>User: Return error + end + + alt SimulateAndExecute is true + BroadcastTx->>Factory: calculateGas(msgs...) + Factory->>Factory: Simulate(msgs...) + Factory->>Factory: WithGas(adjusted) + end + + BroadcastTx->>Factory: BuildUnsignedTx(msgs...) + Factory->>Factory: setMsgs(msgs...) + Factory->>Factory: setMemo(f.txParams.memo) + Factory->>Factory: setFees(f.txParams.gasPrices) + Factory->>Factory: setGasLimit(f.txParams.gas) + Factory->>Factory: setFeeGranter(f.txParams.feeGranter) + Factory->>Factory: setFeePayer(f.txParams.feePayer) + Factory->>Factory: setTimeoutHeight(f.txParams.timeoutHeight) + + alt !clientCtx.SkipConfirm + BroadcastTx->>Factory: getTx() + BroadcastTx->>Factory: txConfig.TxJSONEncoder() + BroadcastTx->>clientCtx: PrintRaw(txBytes) + BroadcastTx->>clientCtx: Input.GetConfirmation() + alt Not confirmed + BroadcastTx-->>GenerateOrBroadcastTxCLI: Return error + GenerateOrBroadcastTxCLI-->>User: Return error + end + end + + BroadcastTx->>Factory: BuildsSignedTx(ctx, msgs...) + Factory->>Factory: sign(ctx, true) + Factory->>Factory: keybase.GetPubKey(fromName) + Factory->>Factory: getSignBytesAdapter() + Factory->>Factory: keybase.Sign(fromName, bytesToSign, signMode) + Factory->>Factory: setSignatures(sig) + Factory->>Factory: getTx() + + BroadcastTx->>Factory: txConfig.TxEncoder() + BroadcastTx->>clientCtx: BroadcastTx(txBytes) + + alt Error in BroadcastTx + clientCtx-->>BroadcastTx: Return error + BroadcastTx-->>GenerateOrBroadcastTxCLI: Return error + GenerateOrBroadcastTxCLI-->>User: Return error + end + + BroadcastTx->>clientCtx: OutputTx(res) + clientCtx-->>BroadcastTx: Return result + BroadcastTx-->>GenerateOrBroadcastTxCLI: Return result + GenerateOrBroadcastTxCLI-->>User: Return result +``` + +## Usage + +To use the `tx` package, typically you would: + +1. Create a `Factory` +2. Simulate the transaction (optional) +3. Build a signed transaction +4. Encode the transaction +5. Broadcast the transaction + +Here's a simplified example: + +```go +// Create a Factory +factory, err := NewFactory(keybase, cdc, accountRetriever, txConfig, addressCodec, conn, txParameters) +if err != nil { + return err +} + +// Simulate the transaction (optional) +simRes, gas, err := factory.Simulate(msgs...) +if err != nil { + return err +} +factory.WithGas(gas) + +// Build a signed transaction +signedTx, err := factory.BuildsSignedTx(context.Background(), msgs...) +if err != nil { + return err +} + +// Encode the transaction +txBytes, err := factory.txConfig.TxEncoder()(signedTx) +if err != nil { + return err +} + +// Broadcast the transaction +// (This step depends on your specific client implementation) +``` \ No newline at end of file diff --git a/client/v2/tx/common_test.go b/client/v2/tx/common_test.go new file mode 100644 index 000000000000..3b474e9fef7a --- /dev/null +++ b/client/v2/tx/common_test.go @@ -0,0 +1,116 @@ +package tx + +import ( + "context" + + "google.golang.org/grpc" + + abciv1beta1 "cosmossdk.io/api/cosmos/base/abci/v1beta1" + apitx "cosmossdk.io/api/cosmos/tx/v1beta1" + "cosmossdk.io/client/v2/autocli/keyring" + "cosmossdk.io/client/v2/internal/account" + txdecode "cosmossdk.io/x/tx/decode" + "cosmossdk.io/x/tx/signing" + + "github.com/cosmos/cosmos-sdk/codec" + addrcodec "github.com/cosmos/cosmos-sdk/codec/address" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + codec2 "github.com/cosmos/cosmos-sdk/crypto/codec" + "github.com/cosmos/cosmos-sdk/crypto/hd" + cryptoKeyring "github.com/cosmos/cosmos-sdk/crypto/keyring" + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" + "github.com/cosmos/cosmos-sdk/types" +) + +var ( + cdc = codec.NewProtoCodec(codectypes.NewInterfaceRegistry()) + ac = addrcodec.NewBech32Codec("cosmos") + valCodec = addrcodec.NewBech32Codec("cosmosval") + signingOptions = signing.Options{ + AddressCodec: ac, + ValidatorAddressCodec: valCodec, + } + signingContext, _ = signing.NewContext(signingOptions) + decodeOptions = txdecode.Options{SigningContext: signingContext, ProtoCodec: cdc} + decoder, _ = txdecode.NewDecoder(decodeOptions) + + k = cryptoKeyring.NewInMemory(cdc) + keybase, _ = cryptoKeyring.NewAutoCLIKeyring(k, ac) + txConf, _ = NewTxConfig(ConfigOptions{ + AddressCodec: ac, + Cdc: cdc, + ValidatorAddressCodec: valCodec, + }) +) + +func setKeyring() keyring.Keyring { + registry := codectypes.NewInterfaceRegistry() + codec2.RegisterInterfaces(registry) + cdc := codec.NewProtoCodec(registry) + k := cryptoKeyring.NewInMemory(cdc) + _, err := k.NewAccount("alice", "equip will roof matter pink blind book anxiety banner elbow sun young", "", "m/44'/118'/0'/0/0", hd.Secp256k1) + if err != nil { + panic(err) + } + keybase, err := cryptoKeyring.NewAutoCLIKeyring(k, ac) + if err != nil { + panic(err) + } + return keybase +} + +type mockAccount struct { + addr []byte +} + +func (m mockAccount) GetAddress() types.AccAddress { + return m.addr +} + +func (m mockAccount) GetPubKey() cryptotypes.PubKey { + return nil +} + +func (m mockAccount) GetAccountNumber() uint64 { + return 1 +} + +func (m mockAccount) GetSequence() uint64 { + return 0 +} + +type mockAccountRetriever struct{} + +func (m mockAccountRetriever) GetAccount(_ context.Context, address []byte) (account.Account, error) { + return mockAccount{addr: address}, nil +} + +func (m mockAccountRetriever) GetAccountWithHeight(_ context.Context, address []byte) (account.Account, int64, error) { + return mockAccount{addr: address}, 0, nil +} + +func (m mockAccountRetriever) EnsureExists(_ context.Context, _ []byte) error { + return nil +} + +func (m mockAccountRetriever) GetAccountNumberSequence(_ context.Context, _ []byte) (accNum, accSeq uint64, err error) { + return accNum, accSeq, nil +} + +type mockClientConn struct{} + +func (m mockClientConn) Invoke(_ context.Context, _ string, _, reply interface{}, _ ...grpc.CallOption) error { + simResponse := apitx.SimulateResponse{ + GasInfo: &abciv1beta1.GasInfo{ + GasWanted: 10000, + GasUsed: 7500, + }, + Result: nil, + } + *reply.(*apitx.SimulateResponse) = simResponse // nolint:govet // ignore linting error + return nil +} + +func (m mockClientConn) NewStream(_ context.Context, _ *grpc.StreamDesc, _ string, _ ...grpc.CallOption) (grpc.ClientStream, error) { + return nil, nil +} diff --git a/client/v2/tx/config.go b/client/v2/tx/config.go new file mode 100644 index 000000000000..a500f7c9b009 --- /dev/null +++ b/client/v2/tx/config.go @@ -0,0 +1,338 @@ +package tx + +import ( + "errors" + + "google.golang.org/protobuf/encoding/protojson" + "google.golang.org/protobuf/reflect/protoreflect" + "google.golang.org/protobuf/types/known/anypb" + + apitxsigning "cosmossdk.io/api/cosmos/tx/signing/v1beta1" + "cosmossdk.io/core/address" + txdecode "cosmossdk.io/x/tx/decode" + "cosmossdk.io/x/tx/signing" + "cosmossdk.io/x/tx/signing/aminojson" + "cosmossdk.io/x/tx/signing/direct" + "cosmossdk.io/x/tx/signing/directaux" + "cosmossdk.io/x/tx/signing/textual" + + "github.com/cosmos/cosmos-sdk/codec" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" +) + +var ( + _ TxConfig = txConfig{} + _ TxEncodingConfig = defaultEncodingConfig{} + _ TxSigningConfig = defaultTxSigningConfig{} + + defaultEnabledSignModes = []apitxsigning.SignMode{ + apitxsigning.SignMode_SIGN_MODE_DIRECT, + apitxsigning.SignMode_SIGN_MODE_DIRECT_AUX, + apitxsigning.SignMode_SIGN_MODE_LEGACY_AMINO_JSON, + } +) + +// TxConfig is an interface that a client can use to generate a concrete transaction type +// defined by the application. +type TxConfig interface { + TxEncodingConfig + TxSigningConfig +} + +// TxEncodingConfig defines the interface for transaction encoding and decoding. +// It provides methods for both binary and JSON encoding/decoding. +type TxEncodingConfig interface { + // TxEncoder returns an encoder for binary transaction encoding. + TxEncoder() txEncoder + // TxDecoder returns a decoder for binary transaction decoding. + TxDecoder() txDecoder + // TxJSONEncoder returns an encoder for JSON transaction encoding. + TxJSONEncoder() txEncoder + // TxJSONDecoder returns a decoder for JSON transaction decoding. + TxJSONDecoder() txDecoder + // Decoder returns the Decoder interface for decoding transaction bytes into a DecodedTx. + Decoder() Decoder +} + +// TxSigningConfig defines the interface for transaction signing configurations. +type TxSigningConfig interface { + // SignModeHandler returns a reference to the HandlerMap which manages the different signing modes. + SignModeHandler() *signing.HandlerMap + // SigningContext returns a reference to the Context which holds additional data required during signing. + SigningContext() *signing.Context + // MarshalSignatureJSON takes a slice of Signature objects and returns their JSON encoding. + MarshalSignatureJSON([]Signature) ([]byte, error) + // UnmarshalSignatureJSON takes a JSON byte slice and returns a slice of Signature objects. + UnmarshalSignatureJSON([]byte) ([]Signature, error) +} + +// ConfigOptions defines the configuration options for transaction processing. +type ConfigOptions struct { + AddressCodec address.Codec + Decoder Decoder + Cdc codec.BinaryCodec + + ValidatorAddressCodec address.Codec + FileResolver signing.ProtoFileResolver + TypeResolver signing.TypeResolver + CustomGetSigner map[protoreflect.FullName]signing.GetSignersFunc + MaxRecursionDepth int + + EnablesSignModes []apitxsigning.SignMode + CustomSignModes []signing.SignModeHandler + TextualCoinMetadataQueryFn textual.CoinMetadataQueryFn +} + +// validate checks the ConfigOptions for required fields and sets default values where necessary. +// It returns an error if any required field is missing. +func (c *ConfigOptions) validate() error { + if c.AddressCodec == nil { + return errors.New("address codec cannot be nil") + } + if c.Cdc == nil { + return errors.New("codec cannot be nil") + } + if c.ValidatorAddressCodec == nil { + return errors.New("validator address codec cannot be nil") + } + + // set default signModes if none are provided + if len(c.EnablesSignModes) == 0 { + c.EnablesSignModes = defaultEnabledSignModes + } + return nil +} + +// txConfig is a struct that embeds TxEncodingConfig and TxSigningConfig interfaces. +type txConfig struct { + TxEncodingConfig + TxSigningConfig +} + +// NewTxConfig creates a new TxConfig instance using the provided ConfigOptions. +// It validates the options, initializes the signing context, and sets up the decoder if not provided. +func NewTxConfig(options ConfigOptions) (TxConfig, error) { + err := options.validate() + if err != nil { + return nil, err + } + + signingCtx, err := newDefaultTxSigningConfig(options) + if err != nil { + return nil, err + } + + if options.Decoder == nil { + options.Decoder, err = txdecode.NewDecoder(txdecode.Options{ + SigningContext: signingCtx.SigningContext(), + ProtoCodec: options.Cdc, + }) + if err != nil { + return nil, err + } + } + + return &txConfig{ + TxEncodingConfig: defaultEncodingConfig{ + cdc: options.Cdc, + decoder: options.Decoder, + }, + TxSigningConfig: signingCtx, + }, nil +} + +// defaultEncodingConfig is an empty struct that implements the TxEncodingConfig interface. +type defaultEncodingConfig struct { + cdc codec.BinaryCodec + decoder Decoder +} + +// TxEncoder returns the default transaction encoder. +func (t defaultEncodingConfig) TxEncoder() txEncoder { + return encodeTx +} + +// TxDecoder returns the default transaction decoder. +func (t defaultEncodingConfig) TxDecoder() txDecoder { + return decodeTx(t.cdc, t.decoder) +} + +// TxJSONEncoder returns the default JSON transaction encoder. +func (t defaultEncodingConfig) TxJSONEncoder() txEncoder { + return encodeJsonTx +} + +// TxJSONDecoder returns the default JSON transaction decoder. +func (t defaultEncodingConfig) TxJSONDecoder() txDecoder { + return decodeJsonTx(t.cdc, t.decoder) +} + +// Decoder returns the Decoder instance associated with this encoding configuration. +func (t defaultEncodingConfig) Decoder() Decoder { + return t.decoder +} + +// defaultTxSigningConfig is a struct that holds the signing context and handler map. +type defaultTxSigningConfig struct { + signingCtx *signing.Context + handlerMap *signing.HandlerMap + cdc codec.BinaryCodec +} + +// newDefaultTxSigningConfig creates a new defaultTxSigningConfig instance using the provided ConfigOptions. +// It initializes the signing context and handler map. +func newDefaultTxSigningConfig(opts ConfigOptions) (*defaultTxSigningConfig, error) { + signingCtx, err := newSigningContext(opts) + if err != nil { + return nil, err + } + + handlerMap, err := newHandlerMap(opts, signingCtx) + if err != nil { + return nil, err + } + + return &defaultTxSigningConfig{ + signingCtx: signingCtx, + handlerMap: handlerMap, + cdc: opts.Cdc, + }, nil +} + +// SignModeHandler returns the handler map that manages the different signing modes. +func (t defaultTxSigningConfig) SignModeHandler() *signing.HandlerMap { + return t.handlerMap +} + +// SigningContext returns the signing context that holds additional data required during signing. +func (t defaultTxSigningConfig) SigningContext() *signing.Context { + return t.signingCtx +} + +// MarshalSignatureJSON takes a slice of Signature objects and returns their JSON encoding. +// This method is not yet implemented and will panic if called. +func (t defaultTxSigningConfig) MarshalSignatureJSON(signatures []Signature) ([]byte, error) { + descriptor := make([]*apitxsigning.SignatureDescriptor, len(signatures)) + + for i, sig := range signatures { + descData, err := signatureDataToProto(sig.Data) + if err != nil { + return nil, err + } + + anyPk, err := codectypes.NewAnyWithValue(sig.PubKey) + if err != nil { + return nil, err + } + + descriptor[i] = &apitxsigning.SignatureDescriptor{ + PublicKey: &anypb.Any{ + TypeUrl: codectypes.MsgTypeURL(sig.PubKey), + Value: anyPk.Value, + }, + Data: descData, + Sequence: sig.Sequence, + } + } + + return jsonMarshalOptions.Marshal(&apitxsigning.SignatureDescriptors{Signatures: descriptor}) +} + +// UnmarshalSignatureJSON takes a JSON byte slice and returns a slice of Signature objects. +// This method is not yet implemented and will panic if called. +func (t defaultTxSigningConfig) UnmarshalSignatureJSON(bz []byte) ([]Signature, error) { + var descriptor apitxsigning.SignatureDescriptors + + err := protojson.UnmarshalOptions{}.Unmarshal(bz, &descriptor) + if err != nil { + return nil, err + } + + sigs := make([]Signature, len(descriptor.Signatures)) + for i, desc := range descriptor.Signatures { + var pubkey cryptotypes.PubKey + + anyPk := &codectypes.Any{ + TypeUrl: desc.PublicKey.TypeUrl, + Value: desc.PublicKey.Value, + } + + err = t.cdc.UnpackAny(anyPk, &pubkey) + if err != nil { + return nil, err + } + + data, err := SignatureDataFromProto(desc.Data) + if err != nil { + return nil, err + } + + sigs[i] = Signature{ + PubKey: pubkey, + Data: data, + Sequence: desc.Sequence, + } + } + + return sigs, nil +} + +// newSigningContext creates a new signing context using the provided ConfigOptions. +// Returns a signing.Context instance or an error if initialization fails. +func newSigningContext(opts ConfigOptions) (*signing.Context, error) { + return signing.NewContext(signing.Options{ + FileResolver: opts.FileResolver, + TypeResolver: opts.TypeResolver, + AddressCodec: opts.AddressCodec, + ValidatorAddressCodec: opts.ValidatorAddressCodec, + CustomGetSigners: opts.CustomGetSigner, + MaxRecursionDepth: opts.MaxRecursionDepth, + }) +} + +// newHandlerMap constructs a new HandlerMap based on the provided ConfigOptions and signing context. +// It initializes handlers for each enabled and custom sign mode specified in the options. +func newHandlerMap(opts ConfigOptions, signingCtx *signing.Context) (*signing.HandlerMap, error) { + lenSignModes := len(opts.EnablesSignModes) + handlers := make([]signing.SignModeHandler, lenSignModes+len(opts.CustomSignModes)) + + for i, m := range opts.EnablesSignModes { + var err error + switch m { + case apitxsigning.SignMode_SIGN_MODE_DIRECT: + handlers[i] = &direct.SignModeHandler{} + case apitxsigning.SignMode_SIGN_MODE_TEXTUAL: + if opts.TextualCoinMetadataQueryFn == nil { + return nil, errors.New("cannot enable SIGN_MODE_TEXTUAL without a TextualCoinMetadataQueryFn") + } + handlers[i], err = textual.NewSignModeHandler(textual.SignModeOptions{ + CoinMetadataQuerier: opts.TextualCoinMetadataQueryFn, + FileResolver: signingCtx.FileResolver(), + TypeResolver: signingCtx.TypeResolver(), + }) + if err != nil { + return nil, err + } + case apitxsigning.SignMode_SIGN_MODE_DIRECT_AUX: + handlers[i], err = directaux.NewSignModeHandler(directaux.SignModeHandlerOptions{ + TypeResolver: signingCtx.TypeResolver(), + SignersContext: signingCtx, + }) + if err != nil { + return nil, err + } + case apitxsigning.SignMode_SIGN_MODE_LEGACY_AMINO_JSON: + handlers[i] = aminojson.NewSignModeHandler(aminojson.SignModeHandlerOptions{ + FileResolver: signingCtx.FileResolver(), + TypeResolver: opts.TypeResolver, + }) + } + } + for i, m := range opts.CustomSignModes { + handlers[i+lenSignModes] = m + } + + handler := signing.NewHandlerMap(handlers...) + return handler, nil +} diff --git a/client/v2/tx/config_test.go b/client/v2/tx/config_test.go new file mode 100644 index 000000000000..7d1f223d1214 --- /dev/null +++ b/client/v2/tx/config_test.go @@ -0,0 +1,293 @@ +package tx + +import ( + "context" + "testing" + + "github.com/stretchr/testify/require" + + apicrypto "cosmossdk.io/api/cosmos/crypto/multisig/v1beta1" + _ "cosmossdk.io/api/cosmos/crypto/secp256k1" + apitxsigning "cosmossdk.io/api/cosmos/tx/signing/v1beta1" + "cosmossdk.io/x/tx/signing" + + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/codec/address" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + codec2 "github.com/cosmos/cosmos-sdk/crypto/codec" + kmultisig "github.com/cosmos/cosmos-sdk/crypto/keys/multisig" + "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" +) + +type mockModeHandler struct{} + +func (t mockModeHandler) Mode() apitxsigning.SignMode { + return apitxsigning.SignMode_SIGN_MODE_DIRECT +} + +func (t mockModeHandler) GetSignBytes(_ context.Context, _ signing.SignerData, _ signing.TxData) ([]byte, error) { + return []byte{}, nil +} + +func TestConfigOptions_validate(t *testing.T) { + tests := []struct { + name string + opts ConfigOptions + wantErr bool + }{ + { + name: "valid options", + opts: ConfigOptions{ + AddressCodec: address.NewBech32Codec("cosmos"), + Decoder: decoder, + Cdc: cdc, + ValidatorAddressCodec: address.NewBech32Codec("cosmosvaloper"), + }, + }, + { + name: "missing address codec", + opts: ConfigOptions{ + Decoder: decoder, + Cdc: cdc, + ValidatorAddressCodec: address.NewBech32Codec("cosmosvaloper"), + }, + wantErr: true, + }, + { + name: "missing decoder", + opts: ConfigOptions{ + AddressCodec: address.NewBech32Codec("cosmos"), + Cdc: cdc, + ValidatorAddressCodec: address.NewBech32Codec("cosmosvaloper"), + }, + }, + { + name: "missing codec", + opts: ConfigOptions{ + AddressCodec: address.NewBech32Codec("cosmos"), + Decoder: decoder, + ValidatorAddressCodec: address.NewBech32Codec("cosmosvaloper"), + }, + wantErr: true, + }, + { + name: "missing validator address codec", + opts: ConfigOptions{ + AddressCodec: address.NewBech32Codec("cosmos"), + Decoder: decoder, + Cdc: cdc, + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := tt.opts.validate(); (err != nil) != tt.wantErr { + t.Errorf("validate() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} + +func Test_newHandlerMap(t *testing.T) { + tests := []struct { + name string + opts ConfigOptions + }{ + { + name: "handler map with default sign modes", + opts: ConfigOptions{ + AddressCodec: address.NewBech32Codec("cosmos"), + Decoder: decoder, + Cdc: cdc, + ValidatorAddressCodec: address.NewBech32Codec("cosmosvaloper"), + }, + }, + { + name: "handler map with just one sign mode", + opts: ConfigOptions{ + AddressCodec: address.NewBech32Codec("cosmos"), + Decoder: decoder, + Cdc: cdc, + ValidatorAddressCodec: address.NewBech32Codec("cosmosvaloper"), + EnablesSignModes: []apitxsigning.SignMode{apitxsigning.SignMode_SIGN_MODE_DIRECT}, + }, + }, + { + name: "handler map with custom sign modes", + opts: ConfigOptions{ + AddressCodec: address.NewBech32Codec("cosmos"), + Decoder: decoder, + Cdc: cdc, + ValidatorAddressCodec: address.NewBech32Codec("cosmosvaloper"), + CustomSignModes: []signing.SignModeHandler{mockModeHandler{}}, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + err := tt.opts.validate() + require.NoError(t, err) + + signingCtx, err := newSigningContext(tt.opts) + require.NoError(t, err) + + handlerMap, err := newHandlerMap(tt.opts, signingCtx) + require.NoError(t, err) + require.NotNil(t, handlerMap) + require.Equal(t, len(handlerMap.SupportedModes()), len(tt.opts.EnablesSignModes)+len(tt.opts.CustomSignModes)) + }) + } +} + +func TestNewTxConfig(t *testing.T) { + tests := []struct { + name string + options ConfigOptions + wantErr bool + }{ + { + name: "valid options", + options: ConfigOptions{ + AddressCodec: ac, + Cdc: cdc, + ValidatorAddressCodec: valCodec, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := NewTxConfig(tt.options) + if (err != nil) != tt.wantErr { + t.Errorf("NewTxConfig() error = %v, wantErr %v", err, tt.wantErr) + return + } + require.NotNil(t, got) + }) + } +} + +func Test_defaultTxSigningConfig_MarshalSignatureJSON(t *testing.T) { + tests := []struct { + name string + options ConfigOptions + signatures func(t *testing.T) []Signature + }{ + { + name: "single signature", + options: ConfigOptions{ + AddressCodec: ac, + Cdc: cdc, + ValidatorAddressCodec: valCodec, + }, + signatures: func(t *testing.T) []Signature { + t.Helper() + + k := setKeyring() + pk, err := k.GetPubKey("alice") + require.NoError(t, err) + signature, err := k.Sign("alice", make([]byte, 10), apitxsigning.SignMode_SIGN_MODE_DIRECT) + require.NoError(t, err) + return []Signature{ + { + PubKey: pk, + Data: &SingleSignatureData{ + SignMode: apitxsigning.SignMode_SIGN_MODE_DIRECT, + Signature: signature, + }, + }, + } + }, + }, + { + name: "multisig signatures", + options: ConfigOptions{ + AddressCodec: ac, + Cdc: cdc, + ValidatorAddressCodec: valCodec, + }, + signatures: func(t *testing.T) []Signature { + t.Helper() + + n := 2 + pubKeys := make([]cryptotypes.PubKey, n) + sigs := make([]SignatureData, n) + for i := 0; i < n; i++ { + sk := secp256k1.GenPrivKey() + pubKeys[i] = sk.PubKey() + msg, err := sk.Sign(make([]byte, 10)) + require.NoError(t, err) + sigs[i] = &SingleSignatureData{ + SignMode: apitxsigning.SignMode_SIGN_MODE_DIRECT, + Signature: msg, + } + } + bitArray := cryptotypes.NewCompactBitArray(n) + mKey := kmultisig.NewLegacyAminoPubKey(n, pubKeys) + return []Signature{ + { + PubKey: mKey, + Data: &MultiSignatureData{ + BitArray: &apicrypto.CompactBitArray{ + ExtraBitsStored: bitArray.ExtraBitsStored, + Elems: bitArray.Elems, + }, + Signatures: sigs, + }, + }, + } + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + config, err := NewTxConfig(tt.options) + require.NoError(t, err) + + got, err := config.MarshalSignatureJSON(tt.signatures(t)) + require.NoError(t, err) + require.NotNil(t, got) + }) + } +} + +func Test_defaultTxSigningConfig_UnmarshalSignatureJSON(t *testing.T) { + registry := codectypes.NewInterfaceRegistry() + codec2.RegisterInterfaces(registry) + cdc := codec.NewProtoCodec(registry) + tests := []struct { + name string + options ConfigOptions + bz []byte + }{ + { + name: "single signature", + options: ConfigOptions{ + AddressCodec: ac, + Cdc: cdc, + ValidatorAddressCodec: valCodec, + }, + bz: []byte(`{"signatures":[{"public_key":{"@type":"/cosmos.crypto.secp256k1.PubKey", "key":"A0/vnNfExjWI07A/61KBudIyy6NNbz1xruWSEf+/4f6H"}, "data":{"single":{"mode":"SIGN_MODE_DIRECT", "signature":"usUTJwdc4PWPuox0Y0G/RuHoxyj+QpUcBGvXyNdDX1FOdoVj0tg4TGKT2NnM3QP6wCNbubjHuMOhTtqfW8SkYg=="}}}]}`), + }, + { + name: "multisig signatures", + options: ConfigOptions{ + AddressCodec: ac, + Cdc: cdc, + ValidatorAddressCodec: valCodec, + }, + bz: []byte(`{"signatures":[{"public_key":{"@type":"/cosmos.crypto.multisig.LegacyAminoPubKey","threshold":2,"public_keys":[{"@type":"/cosmos.crypto.secp256k1.PubKey","key":"A4Bs9huvS/COpZNhVhTnhgc8YR6VrSQ8hLQIHgnA+m3w"},{"@type":"/cosmos.crypto.secp256k1.PubKey","key":"AuNz2lFkLn3sKNjC5r4OWhgkWg5DZpGUiR9OdpzXspnp"}]},"data":{"multi":{"bitarray":{"extra_bits_stored":2,"elems":"AA=="},"signatures":[{"single":{"mode":"SIGN_MODE_DIRECT","signature":"vng4IlPzLH3fDFpikM5y1SfXFGny4BcLGwIFU0Ty4yoWjIxjTS4m6fgDB61sxEkV5DK/CD7gUwenGuEpzJ2IGw=="}},{"single":{"mode":"SIGN_MODE_DIRECT","signature":"2dsGmr13bq/mPxbk9AgqcFpuvk4beszWu6uxkx+EhTMdVGp4J8FtjZc8xs/Pp3oTWY4ScAORYQHxwqN4qwMXGg=="}}]}}}]}`), + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + config, err := NewTxConfig(tt.options) + require.NoError(t, err) + + got, err := config.UnmarshalSignatureJSON(tt.bz) + require.NoError(t, err) + require.NotNil(t, got) + }) + } +} diff --git a/client/v2/tx/encoder.go b/client/v2/tx/encoder.go new file mode 100644 index 000000000000..2094efe6d3d5 --- /dev/null +++ b/client/v2/tx/encoder.go @@ -0,0 +1,119 @@ +package tx + +import ( + "fmt" + + "google.golang.org/protobuf/encoding/protojson" + protov2 "google.golang.org/protobuf/proto" + + txv1beta1 "cosmossdk.io/api/cosmos/tx/v1beta1" + txdecode "cosmossdk.io/x/tx/decode" + + "github.com/cosmos/cosmos-sdk/codec" +) + +var ( + // marshalOption configures protobuf marshaling to be deterministic. + marshalOption = protov2.MarshalOptions{Deterministic: true} + + // jsonMarshalOptions configures JSON marshaling for protobuf messages. + jsonMarshalOptions = protojson.MarshalOptions{ + Indent: "", + UseProtoNames: true, + UseEnumNumbers: false, + } +) + +// Decoder defines the interface for decoding transaction bytes into a DecodedTx. +type Decoder interface { + Decode(txBytes []byte) (*txdecode.DecodedTx, error) +} + +// txDecoder is a function type that unmarshals transaction bytes into an API Tx type. +type txDecoder func(txBytes []byte) (Tx, error) + +// txEncoder is a function type that marshals a transaction into bytes. +type txEncoder func(tx Tx) ([]byte, error) + +// decodeTx decodes transaction bytes into an apitx.Tx structure. +func decodeTx(cdc codec.BinaryCodec, decoder Decoder) txDecoder { + return func(txBytes []byte) (Tx, error) { + tx := new(txv1beta1.Tx) + err := protov2.Unmarshal(txBytes, tx) + if err != nil { + return nil, err + } + + pTxBytes, err := protoTxBytes(tx) + if err != nil { + return nil, err + } + + decodedTx, err := decoder.Decode(pTxBytes) + if err != nil { + return nil, err + } + return newWrapperTx(cdc, decodedTx), nil + } +} + +// encodeTx encodes an apitx.Tx into bytes using protobuf marshaling options. +func encodeTx(tx Tx) ([]byte, error) { + wTx, ok := tx.(*wrappedTx) + if !ok { + return nil, fmt.Errorf("unexpected tx type: %T", tx) + } + return marshalOption.Marshal(wTx.Tx) +} + +// decodeJsonTx decodes transaction bytes into an apitx.Tx structure using JSON format. +func decodeJsonTx(cdc codec.BinaryCodec, decoder Decoder) txDecoder { + return func(txBytes []byte) (Tx, error) { + jsonTx := new(txv1beta1.Tx) + err := protojson.UnmarshalOptions{ + AllowPartial: false, + DiscardUnknown: false, + }.Unmarshal(txBytes, jsonTx) + if err != nil { + return nil, err + } + + pTxBytes, err := protoTxBytes(jsonTx) + if err != nil { + return nil, err + } + + decodedTx, err := decoder.Decode(pTxBytes) + if err != nil { + return nil, err + } + return newWrapperTx(cdc, decodedTx), nil + } +} + +// encodeJsonTx encodes an apitx.Tx into bytes using JSON marshaling options. +func encodeJsonTx(tx Tx) ([]byte, error) { + wTx, ok := tx.(*wrappedTx) + if !ok { + return nil, fmt.Errorf("unexpected tx type: %T", tx) + } + return jsonMarshalOptions.Marshal(wTx.Tx) +} + +func protoTxBytes(tx *txv1beta1.Tx) ([]byte, error) { + bodyBytes, err := marshalOption.Marshal(tx.Body) + if err != nil { + return nil, err + } + + authInfoBytes, err := marshalOption.Marshal(tx.AuthInfo) + if err != nil { + return nil, err + } + + return marshalOption.Marshal(&txv1beta1.TxRaw{ + BodyBytes: bodyBytes, + AuthInfoBytes: authInfoBytes, + Signatures: tx.Signatures, + }) +} diff --git a/client/v2/tx/encoder_test.go b/client/v2/tx/encoder_test.go new file mode 100644 index 000000000000..9dec56762318 --- /dev/null +++ b/client/v2/tx/encoder_test.go @@ -0,0 +1,107 @@ +package tx + +import ( + "testing" + + "github.com/stretchr/testify/require" + + base "cosmossdk.io/api/cosmos/base/v1beta1" + countertypes "cosmossdk.io/api/cosmos/counter/v1" + apisigning "cosmossdk.io/api/cosmos/tx/signing/v1beta1" + "cosmossdk.io/core/transaction" + + "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" +) + +func getWrappedTx(t *testing.T) *wrappedTx { + t.Helper() + + f, err := NewFactory(keybase, cdc, mockAccountRetriever{}, txConf, ac, mockClientConn{}, TxParameters{}) + require.NoError(t, err) + + pk := secp256k1.GenPrivKey().PubKey() + addr, _ := ac.BytesToString(pk.Address()) + + f.tx.msgs = []transaction.Msg{&countertypes.MsgIncreaseCounter{ + Signer: addr, + Count: 0, + }} + require.NoError(t, err) + + err = f.setFeePayer(addr) + require.NoError(t, err) + + f.tx.fees = []*base.Coin{{ + Denom: "cosmos", + Amount: "1000", + }} + + err = f.setSignatures([]Signature{{ + PubKey: pk, + Data: &SingleSignatureData{ + SignMode: apisigning.SignMode_SIGN_MODE_DIRECT, + Signature: nil, + }, + Sequence: 0, + }}...) + require.NoError(t, err) + wTx, err := f.getTx() + require.NoError(t, err) + return wTx +} + +func Test_txEncoder_txDecoder(t *testing.T) { + wTx := getWrappedTx(t) + + encodedTx, err := encodeTx(wTx) + require.NoError(t, err) + require.NotNil(t, encodedTx) + + isDeterministic, err := encodeTx(wTx) + require.NoError(t, err) + require.NotNil(t, encodedTx) + require.Equal(t, encodedTx, isDeterministic) + + f := decodeTx(cdc, decoder) + decodedTx, err := f(encodedTx) + require.NoError(t, err) + require.NotNil(t, decodedTx) + + dTx, ok := decodedTx.(*wrappedTx) + require.True(t, ok) + require.Equal(t, wTx.TxRaw, dTx.TxRaw) + require.Equal(t, wTx.Tx.AuthInfo.String(), dTx.Tx.AuthInfo.String()) + require.Equal(t, wTx.Tx.Body.String(), dTx.Tx.Body.String()) + require.Equal(t, wTx.Tx.Signatures, dTx.Tx.Signatures) +} + +func Test_txJsonEncoder_txJsonDecoder(t *testing.T) { + tests := []struct { + name string + }{ + { + name: "json encode and decode tx", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + wTx := getWrappedTx(t) + + encodedTx, err := encodeJsonTx(wTx) + require.NoError(t, err) + require.NotNil(t, encodedTx) + + f := decodeJsonTx(cdc, decoder) + decodedTx, err := f(encodedTx) + require.NoError(t, err) + require.NotNil(t, decodedTx) + + dTx, ok := decodedTx.(*wrappedTx) + require.True(t, ok) + require.Equal(t, wTx.TxRaw, dTx.TxRaw) + require.Equal(t, wTx.Tx.AuthInfo.String(), dTx.Tx.AuthInfo.String()) + require.Equal(t, wTx.Tx.Body.String(), dTx.Tx.Body.String()) + require.Equal(t, wTx.Tx.Signatures, dTx.Tx.Signatures) + }) + } +} diff --git a/client/v2/tx/factory.go b/client/v2/tx/factory.go new file mode 100644 index 000000000000..9dd0eae21a34 --- /dev/null +++ b/client/v2/tx/factory.go @@ -0,0 +1,761 @@ +package tx + +import ( + "context" + "errors" + "fmt" + "math/big" + "strings" + + "github.com/cosmos/go-bip39" + gogogrpc "github.com/cosmos/gogoproto/grpc" + "github.com/spf13/pflag" + "google.golang.org/protobuf/types/known/anypb" + "google.golang.org/protobuf/types/known/timestamppb" + + base "cosmossdk.io/api/cosmos/base/v1beta1" + apicrypto "cosmossdk.io/api/cosmos/crypto/multisig/v1beta1" + apitxsigning "cosmossdk.io/api/cosmos/tx/signing/v1beta1" + apitx "cosmossdk.io/api/cosmos/tx/v1beta1" + "cosmossdk.io/client/v2/autocli/keyring" + "cosmossdk.io/client/v2/internal/account" + "cosmossdk.io/client/v2/internal/coins" + "cosmossdk.io/core/address" + "cosmossdk.io/core/transaction" + "cosmossdk.io/math" + "cosmossdk.io/x/tx/signing" + + flags2 "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/cosmos/cosmos-sdk/codec" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + "github.com/cosmos/cosmos-sdk/crypto/keys/multisig" + "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" +) + +// Factory defines a client transaction factory that facilitates generating and +// signing an application-specific transaction. +type Factory struct { + keybase keyring.Keyring + cdc codec.BinaryCodec + accountRetriever account.AccountRetriever + ac address.Codec + conn gogogrpc.ClientConn + txConfig TxConfig + txParams TxParameters + + tx txState +} + +func NewFactoryFromFlagSet(flags *pflag.FlagSet, keybase keyring.Keyring, cdc codec.BinaryCodec, accRetriever account.AccountRetriever, + txConfig TxConfig, ac address.Codec, conn gogogrpc.ClientConn, +) (Factory, error) { + offline, _ := flags.GetBool(flags2.FlagOffline) + if err := validateFlagSet(flags, offline); err != nil { + return Factory{}, err + } + + params, err := txParamsFromFlagSet(flags, keybase, ac) + if err != nil { + return Factory{}, err + } + + params, err = prepareTxParams(params, accRetriever, offline) + if err != nil { + return Factory{}, err + } + + return NewFactory(keybase, cdc, accRetriever, txConfig, ac, conn, params) +} + +// NewFactory returns a new instance of Factory. +func NewFactory(keybase keyring.Keyring, cdc codec.BinaryCodec, accRetriever account.AccountRetriever, + txConfig TxConfig, ac address.Codec, conn gogogrpc.ClientConn, parameters TxParameters, +) (Factory, error) { + return Factory{ + keybase: keybase, + cdc: cdc, + accountRetriever: accRetriever, + ac: ac, + conn: conn, + txConfig: txConfig, + txParams: parameters, + + tx: txState{}, + }, nil +} + +// validateFlagSet checks the provided flags for consistency and requirements based on the operation mode. +func validateFlagSet(flags *pflag.FlagSet, offline bool) error { + if offline { + if !flags.Changed(flags2.FlagAccountNumber) || !flags.Changed(flags2.FlagSequence) { + return errors.New("account-number and sequence must be set in offline mode") + } + + gas, _ := flags.GetString(flags2.FlagGas) + gasSetting, _ := flags2.ParseGasSetting(gas) + if gasSetting.Simulate { + return errors.New("simulate and offline flags cannot be set at the same time") + } + } + + generateOnly, _ := flags.GetBool(flags2.FlagGenerateOnly) + chainID, _ := flags.GetString(flags2.FlagChainID) + if offline && generateOnly && chainID != "" { + return errors.New("chain ID cannot be used when offline and generate-only flags are set") + } + if chainID == "" { + return errors.New("chain ID required but not specified") + } + + dryRun, _ := flags.GetBool(flags2.FlagDryRun) + if offline && dryRun { + return errors.New("dry-run: cannot use offline mode") + } + + return nil +} + +// prepareTxParams ensures the account defined by ctx.GetFromAddress() exists and +// if the account number and/or the account sequence number are zero (not set), +// they will be queried for and set on the provided Factory. +func prepareTxParams(parameters TxParameters, accRetriever account.AccountRetriever, offline bool) (TxParameters, error) { + if offline { + return parameters, nil + } + + if len(parameters.address) == 0 { + return parameters, errors.New("missing 'from address' field") + } + + if parameters.accountNumber == 0 || parameters.sequence == 0 { + num, seq, err := accRetriever.GetAccountNumberSequence(context.Background(), parameters.address) + if err != nil { + return parameters, err + } + + if parameters.accountNumber == 0 { + parameters.accountNumber = num + } + + if parameters.sequence == 0 { + parameters.sequence = seq + } + } + + return parameters, nil +} + +// BuildUnsignedTx builds a transaction to be signed given a set of messages. +// Once created, the fee, memo, and messages are set. +func (f *Factory) BuildUnsignedTx(msgs ...transaction.Msg) error { + fees := f.txParams.fees + + isGasPriceZero, err := coins.IsZero(f.txParams.gasPrices) + if err != nil { + return err + } + if !isGasPriceZero { + areFeesZero, err := coins.IsZero(fees) + if err != nil { + return err + } + if !areFeesZero { + return errors.New("cannot provide both fees and gas prices") + } + + // f.gas is an uint64 and we should convert to LegacyDec + // without the risk of under/overflow via uint64->int64. + glDec := math.LegacyNewDecFromBigInt(new(big.Int).SetUint64(f.txParams.gas)) + + // Derive the fees based on the provided gas prices, where + // fee = ceil(gasPrice * gasLimit). + fees = make([]*base.Coin, len(f.txParams.gasPrices)) + + for i, gp := range f.txParams.gasPrices { + fee, err := math.LegacyNewDecFromStr(gp.Amount) + if err != nil { + return err + } + fee = fee.Mul(glDec) + fees[i] = &base.Coin{Denom: gp.Denom, Amount: fee.Ceil().RoundInt().String()} + } + } + + if err := validateMemo(f.txParams.memo); err != nil { + return err + } + + f.tx.msgs = msgs + f.tx.memo = f.txParams.memo + f.tx.fees = fees + f.tx.gasLimit = f.txParams.gas + f.tx.unordered = f.txParams.unordered + f.tx.timeoutTimestamp = f.txParams.timeoutTimestamp + + err = f.setFeeGranter(f.txParams.feeGranter) + if err != nil { + return err + } + err = f.setFeePayer(f.txParams.feePayer) + if err != nil { + return err + } + + return nil +} + +func (f *Factory) BuildsSignedTx(ctx context.Context, msgs ...transaction.Msg) (Tx, error) { + err := f.BuildUnsignedTx(msgs...) + if err != nil { + return nil, err + } + + return f.sign(ctx, true) +} + +// calculateGas calculates the gas required for the given messages. +func (f *Factory) calculateGas(msgs ...transaction.Msg) error { + _, adjusted, err := f.Simulate(msgs...) + if err != nil { + return err + } + + f.WithGas(adjusted) + + return nil +} + +// Simulate simulates the execution of a transaction and returns the +// simulation response obtained by the query and the adjusted gas amount. +func (f *Factory) Simulate(msgs ...transaction.Msg) (*apitx.SimulateResponse, uint64, error) { + txBytes, err := f.BuildSimTx(msgs...) + if err != nil { + return nil, 0, err + } + + txSvcClient := apitx.NewServiceClient(f.conn) + simRes, err := txSvcClient.Simulate(context.Background(), &apitx.SimulateRequest{ + TxBytes: txBytes, + }) + if err != nil { + return nil, 0, err + } + + return simRes, uint64(f.gasAdjustment() * float64(simRes.GasInfo.GasUsed)), nil +} + +// UnsignedTxString will generate an unsigned transaction and print it to the writer +// specified by ctx.Output. If simulation was requested, the gas will be +// simulated and also printed to the same writer before the transaction is +// printed. +func (f *Factory) UnsignedTxString(msgs ...transaction.Msg) (string, error) { + if f.simulateAndExecute() { + err := f.calculateGas(msgs...) + if err != nil { + return "", err + } + } + + err := f.BuildUnsignedTx(msgs...) + if err != nil { + return "", err + } + + encoder := f.txConfig.TxJSONEncoder() + if encoder == nil { + return "", errors.New("cannot print unsigned tx: tx json encoder is nil") + } + + tx, err := f.getTx() + if err != nil { + return "", err + } + + json, err := encoder(tx) + if err != nil { + return "", err + } + + return fmt.Sprintf("%s\n", json), nil +} + +// BuildSimTx creates an unsigned tx with an empty single signature and returns +// the encoded transaction or an error if the unsigned transaction cannot be +// built. +func (f *Factory) BuildSimTx(msgs ...transaction.Msg) ([]byte, error) { + err := f.BuildUnsignedTx(msgs...) + if err != nil { + return nil, err + } + + pk, err := f.getSimPK() + if err != nil { + return nil, err + } + + // Create an empty signature literal as the ante handler will populate with a + // sentinel pubkey. + sig := Signature{ + PubKey: pk, + Data: f.getSimSignatureData(pk), + Sequence: f.sequence(), + } + if err := f.setSignatures(sig); err != nil { + return nil, err + } + + encoder := f.txConfig.TxEncoder() + if encoder == nil { + return nil, fmt.Errorf("cannot simulate tx: tx encoder is nil") + } + + tx, err := f.getTx() + if err != nil { + return nil, err + } + return encoder(tx) +} + +// sign signs a given tx with a named key. The bytes signed over are canonical. +// The resulting signature will be added to the transaction builder overwriting the previous +// ones if overwrite=true (otherwise, the signature will be appended). +// Signing a transaction with multiple signers in the DIRECT mode is not supported and will +// return an error. +func (f *Factory) sign(ctx context.Context, overwriteSig bool) (Tx, error) { + if f.keybase == nil { + return nil, errors.New("keybase must be set prior to signing a transaction") + } + + var err error + if f.txParams.signMode == apitxsigning.SignMode_SIGN_MODE_UNSPECIFIED { + f.txParams.signMode = f.txConfig.SignModeHandler().DefaultMode() + } + + pubKey, err := f.keybase.GetPubKey(f.txParams.fromName) + if err != nil { + return nil, err + } + + addr, err := f.ac.BytesToString(pubKey.Address()) + if err != nil { + return nil, err + } + + signerData := signing.SignerData{ + ChainID: f.txParams.chainID, + AccountNumber: f.txParams.accountNumber, + Sequence: f.txParams.sequence, + PubKey: &anypb.Any{ + TypeUrl: codectypes.MsgTypeURL(pubKey), + Value: pubKey.Bytes(), + }, + Address: addr, + } + + // For SIGN_MODE_DIRECT, we need to set the SignerInfos before generating + // the sign bytes. This is done by calling setSignatures with a nil + // signature, which in turn calls setSignerInfos internally. + // + // For SIGN_MODE_LEGACY_AMINO, this step is not strictly necessary, + // but we include it for consistency across all sign modes. + // It does not affect the generated sign bytes for LEGACY_AMINO. + // + // By setting the signatures here, we ensure that the correct SignerInfos + // are in place for all subsequent operations, regardless of the sign mode. + sigData := SingleSignatureData{ + SignMode: f.txParams.signMode, + Signature: nil, + } + sig := Signature{ + PubKey: pubKey, + Data: &sigData, + Sequence: f.txParams.sequence, + } + + var prevSignatures []Signature + if !overwriteSig { + tx, err := f.getTx() + if err != nil { + return nil, err + } + + prevSignatures, err = tx.GetSignatures() + if err != nil { + return nil, err + } + } + // Overwrite or append signer infos. + var sigs []Signature + if overwriteSig { + sigs = []Signature{sig} + } else { + sigs = append(sigs, prevSignatures...) + sigs = append(sigs, sig) + } + if err := f.setSignatures(sigs...); err != nil { + return nil, err + } + + tx, err := f.getTx() + if err != nil { + return nil, err + } + + if err := checkMultipleSigners(tx); err != nil { + return nil, err + } + + bytesToSign, err := f.getSignBytesAdapter(ctx, signerData) + if err != nil { + return nil, err + } + + // Sign those bytes + sigBytes, err := f.keybase.Sign(f.txParams.fromName, bytesToSign, f.txParams.signMode) + if err != nil { + return nil, err + } + + // Construct the SignatureV2 struct + sigData = SingleSignatureData{ + SignMode: f.signMode(), + Signature: sigBytes, + } + sig = Signature{ + PubKey: pubKey, + Data: &sigData, + Sequence: f.txParams.sequence, + } + + if overwriteSig { + err = f.setSignatures(sig) + } else { + prevSignatures = append(prevSignatures, sig) + err = f.setSignatures(prevSignatures...) + } + + if err != nil { + return nil, fmt.Errorf("unable to set signatures on payload: %w", err) + } + + return f.getTx() +} + +// getSignBytesAdapter returns the sign bytes for a given transaction and sign mode. +func (f *Factory) getSignBytesAdapter(ctx context.Context, signerData signing.SignerData) ([]byte, error) { + txData, err := f.getSigningTxData() + if err != nil { + return nil, err + } + + // Generate the bytes to be signed. + return f.txConfig.SignModeHandler().GetSignBytes(ctx, f.signMode(), signerData, *txData) +} + +// WithGas returns a copy of the Factory with an updated gas value. +func (f *Factory) WithGas(gas uint64) { + f.txParams.gas = gas +} + +// WithSequence returns a copy of the Factory with an updated sequence number. +func (f *Factory) WithSequence(sequence uint64) { + f.txParams.sequence = sequence +} + +// WithAccountNumber returns a copy of the Factory with an updated account number. +func (f *Factory) WithAccountNumber(accnum uint64) { + f.txParams.accountNumber = accnum +} + +// sequence returns the sequence number. +func (f *Factory) sequence() uint64 { return f.txParams.sequence } + +// gasAdjustment returns the gas adjustment value. +func (f *Factory) gasAdjustment() float64 { return f.txParams.gasAdjustment } + +// simulateAndExecute returns whether to simulate and execute. +func (f *Factory) simulateAndExecute() bool { return f.txParams.simulateAndExecute } + +// signMode returns the sign mode. +func (f *Factory) signMode() apitxsigning.SignMode { return f.txParams.signMode } + +// getSimPK gets the public key to use for building a simulation tx. +// Note, we should only check for keys in the keybase if we are in simulate and execute mode, +// e.g. when using --gas=auto. +// When using --dry-run, we are is simulation mode only and should not check the keybase. +// Ref: https://github.com/cosmos/cosmos-sdk/issues/11283 +func (f *Factory) getSimPK() (cryptotypes.PubKey, error) { + var ( + err error + pk cryptotypes.PubKey = &secp256k1.PubKey{} + ) + + if f.txParams.simulateAndExecute && f.keybase != nil { + pk, err = f.keybase.GetPubKey(f.txParams.fromName) + if err != nil { + return nil, err + } + } else { + // When in dry-run mode, attempt to retrieve the account using the provided address. + // If the account retrieval fails, the default public key is used. + acc, err := f.accountRetriever.GetAccount(context.Background(), f.txParams.address) + if err != nil { + // If there is an error retrieving the account, return the default public key. + return pk, nil + } + // If the account is successfully retrieved, use its public key. + pk = acc.GetPubKey() + } + + return pk, nil +} + +// getSimSignatureData based on the pubKey type gets the correct SignatureData type +// to use for building a simulation tx. +func (f *Factory) getSimSignatureData(pk cryptotypes.PubKey) SignatureData { + multisigPubKey, ok := pk.(*multisig.LegacyAminoPubKey) + if !ok { + return &SingleSignatureData{SignMode: f.txParams.signMode} + } + + multiSignatureData := make([]SignatureData, 0, multisigPubKey.Threshold) + for i := uint32(0); i < multisigPubKey.Threshold; i++ { + multiSignatureData = append(multiSignatureData, &SingleSignatureData{ + SignMode: f.signMode(), + }) + } + + return &MultiSignatureData{ + BitArray: &apicrypto.CompactBitArray{}, + Signatures: multiSignatureData, + } +} + +func (f *Factory) getTx() (*wrappedTx, error) { + msgs, err := msgsV1toAnyV2(f.tx.msgs) + if err != nil { + return nil, err + } + + body := &apitx.TxBody{ + Messages: msgs, + Memo: f.tx.memo, + TimeoutHeight: f.tx.timeoutHeight, + TimeoutTimestamp: timestamppb.New(f.tx.timeoutTimestamp), + Unordered: f.tx.unordered, + ExtensionOptions: f.tx.extensionOptions, + NonCriticalExtensionOptions: f.tx.nonCriticalExtensionOptions, + } + + fee, err := f.getFee() + if err != nil { + return nil, err + } + + authInfo := &apitx.AuthInfo{ + SignerInfos: f.tx.signerInfos, + Fee: fee, + } + + bodyBytes, err := marshalOption.Marshal(body) + if err != nil { + return nil, err + } + + authInfoBytes, err := marshalOption.Marshal(authInfo) + if err != nil { + return nil, err + } + + txRawBytes, err := marshalOption.Marshal(&apitx.TxRaw{ + BodyBytes: bodyBytes, + AuthInfoBytes: authInfoBytes, + Signatures: f.tx.signatures, + }) + if err != nil { + return nil, err + } + + decodedTx, err := f.txConfig.Decoder().Decode(txRawBytes) + if err != nil { + return nil, err + } + + return newWrapperTx(f.cdc, decodedTx), nil +} + +// getSigningTxData returns a TxData with the current txState info. +func (f *Factory) getSigningTxData() (*signing.TxData, error) { + tx, err := f.getTx() + if err != nil { + return nil, err + } + + return &signing.TxData{ + Body: tx.Tx.Body, + AuthInfo: tx.Tx.AuthInfo, + BodyBytes: tx.TxRaw.BodyBytes, + AuthInfoBytes: tx.TxRaw.AuthInfoBytes, + BodyHasUnknownNonCriticals: tx.TxBodyHasUnknownNonCriticals, + }, nil +} + +// setSignatures sets the signatures for the transaction builder. +// It takes a variable number of Signature arguments and processes each one to extract the mode information and raw signature. +// It also converts the public key to the appropriate format and sets the signer information. +func (f *Factory) setSignatures(signatures ...Signature) error { + n := len(signatures) + signerInfos := make([]*apitx.SignerInfo, n) + rawSignatures := make([][]byte, n) + + for i, sig := range signatures { + var ( + modeInfo *apitx.ModeInfo + pubKey *codectypes.Any + err error + anyPk *anypb.Any + ) + + modeInfo, rawSignatures[i] = signatureDataToModeInfoAndSig(sig.Data) + if sig.PubKey != nil { + pubKey, err = codectypes.NewAnyWithValue(sig.PubKey) + if err != nil { + return err + } + anyPk = &anypb.Any{ + TypeUrl: pubKey.TypeUrl, + Value: pubKey.Value, + } + } + + signerInfos[i] = &apitx.SignerInfo{ + PublicKey: anyPk, + ModeInfo: modeInfo, + Sequence: sig.Sequence, + } + } + + f.tx.signerInfos = signerInfos + f.tx.signatures = rawSignatures + + return nil +} + +// getFee computes the transaction fee information. +// It returns a pointer to an apitx.Fee struct containing the fee amount, gas limit, payer, and granter information. +// If the granter or payer addresses are set, it converts them from bytes to string using the addressCodec. +func (f *Factory) getFee() (fee *apitx.Fee, err error) { + granterStr := "" + if f.tx.granter != nil { + granterStr, err = f.ac.BytesToString(f.tx.granter) + if err != nil { + return nil, err + } + } + + payerStr := "" + if f.tx.payer != nil { + payerStr, err = f.ac.BytesToString(f.tx.payer) + if err != nil { + return nil, err + } + } + + fee = &apitx.Fee{ + Amount: f.tx.fees, + GasLimit: f.tx.gasLimit, + Payer: payerStr, + Granter: granterStr, + } + + return fee, nil +} + +// setFeePayer sets the fee payer for the transaction. +func (f *Factory) setFeePayer(feePayer string) error { + if feePayer == "" { + return nil + } + + addr, err := f.ac.StringToBytes(feePayer) + if err != nil { + return err + } + f.tx.payer = addr + return nil +} + +// setFeeGranter sets the fee granter's address in the transaction builder. +// If the feeGranter string is empty, the function returns nil without setting an address. +// It converts the feeGranter string to bytes using the address codec and sets it as the granter address. +// Returns an error if the conversion fails. +func (f *Factory) setFeeGranter(feeGranter string) error { + if feeGranter == "" { + return nil + } + + addr, err := f.ac.StringToBytes(feeGranter) + if err != nil { + return err + } + f.tx.granter = addr + + return nil +} + +// msgsV1toAnyV2 converts a slice of transaction.Msg (v1) to a slice of anypb.Any (v2). +// It first converts each transaction.Msg into a codectypes.Any and then converts +// these into anypb.Any. +func msgsV1toAnyV2(msgs []transaction.Msg) ([]*anypb.Any, error) { + anys := make([]*codectypes.Any, len(msgs)) + for i, msg := range msgs { + anyMsg, err := codectypes.NewAnyWithValue(msg) + if err != nil { + return nil, err + } + anys[i] = anyMsg + } + + return intoAnyV2(anys), nil +} + +// intoAnyV2 converts a slice of codectypes.Any (v1) to a slice of anypb.Any (v2). +func intoAnyV2(v1s []*codectypes.Any) []*anypb.Any { + v2s := make([]*anypb.Any, len(v1s)) + for i, v1 := range v1s { + v2s[i] = &anypb.Any{ + TypeUrl: v1.TypeUrl, + Value: v1.Value, + } + } + return v2s +} + +// checkMultipleSigners checks that there can be maximum one DIRECT signer in +// a tx. +func checkMultipleSigners(tx Tx) error { + directSigners := 0 + sigsV2, err := tx.GetSignatures() + if err != nil { + return err + } + for _, sig := range sigsV2 { + directSigners += countDirectSigners(sig.Data) + if directSigners > 1 { + return errors.New("txs signed with CLI can have maximum 1 DIRECT signer") + } + } + + return nil +} + +// validateMemo validates the memo field. +func validateMemo(memo string) error { + // Prevent simple inclusion of a valid mnemonic in the memo field + if memo != "" && bip39.IsMnemonicValid(strings.ToLower(memo)) { + return errors.New("cannot provide a valid mnemonic seed in the memo field") + } + + return nil +} diff --git a/client/v2/tx/factory_test.go b/client/v2/tx/factory_test.go new file mode 100644 index 000000000000..39f21b38d0df --- /dev/null +++ b/client/v2/tx/factory_test.go @@ -0,0 +1,921 @@ +package tx + +import ( + "context" + "testing" + + "github.com/stretchr/testify/require" + "google.golang.org/protobuf/types/known/anypb" + + base "cosmossdk.io/api/cosmos/base/v1beta1" + apitxsigning "cosmossdk.io/api/cosmos/tx/signing/v1beta1" + "cosmossdk.io/core/transaction" + "cosmossdk.io/x/tx/signing" + + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" + "github.com/cosmos/cosmos-sdk/crypto/keys/multisig" + "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" + countertypes "github.com/cosmos/cosmos-sdk/testutil/x/counter/types" +) + +var ( + signer = "cosmos1zglwfu6xjzvzagqcmvzewyzjp9xwqw5qwrr8n9" + addr, _ = ac.StringToBytes(signer) +) + +func TestFactory_prepareTxParams(t *testing.T) { + tests := []struct { + name string + txParams TxParameters + error bool + }{ + { + name: "no error", + txParams: TxParameters{ + AccountConfig: AccountConfig{ + address: addr, + }, + }, + }, + { + name: "without account", + txParams: TxParameters{}, + error: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + var err error + tt.txParams, err = prepareTxParams(tt.txParams, mockAccountRetriever{}, false) + if (err != nil) != tt.error { + t.Errorf("Prepare() error = %v, wantErr %v", err, tt.error) + } + }) + } +} + +func TestFactory_BuildUnsignedTx(t *testing.T) { + tests := []struct { + name string + txParams TxParameters + msgs []transaction.Msg + error bool + }{ + { + name: "no error", + txParams: TxParameters{ + chainID: "demo", + AccountConfig: AccountConfig{ + address: addr, + }, + }, + msgs: []transaction.Msg{ + &countertypes.MsgIncreaseCounter{ + Signer: signer, + Count: 0, + }, + }, + }, + { + name: "fees and gas price provided", + txParams: TxParameters{ + chainID: "demo", + AccountConfig: AccountConfig{ + address: addr, + }, + GasConfig: GasConfig{ + gasPrices: []*base.DecCoin{ + { + Amount: "1000", + Denom: "stake", + }, + }, + }, + FeeConfig: FeeConfig{ + fees: []*base.Coin{ + { + Amount: "1000", + Denom: "stake", + }, + }, + }, + }, + msgs: []transaction.Msg{}, + error: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + f, err := NewFactory(keybase, cdc, mockAccountRetriever{}, txConf, ac, mockClientConn{}, tt.txParams) + require.NoError(t, err) + require.NotNil(t, f) + err = f.BuildUnsignedTx(tt.msgs...) + if tt.error { + require.Error(t, err) + } else { + require.NoError(t, err) + require.Nil(t, f.tx.signatures) + require.Nil(t, f.tx.signerInfos) + } + }) + } +} + +func TestFactory_calculateGas(t *testing.T) { + tests := []struct { + name string + txParams TxParameters + msgs []transaction.Msg + error bool + }{ + { + name: "no error", + txParams: TxParameters{ + chainID: "demo", + AccountConfig: AccountConfig{ + address: addr, + }, + GasConfig: GasConfig{ + gasAdjustment: 1, + }, + }, + msgs: []transaction.Msg{ + &countertypes.MsgIncreaseCounter{ + Signer: signer, + Count: 0, + }, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + f, err := NewFactory(keybase, cdc, mockAccountRetriever{}, txConf, ac, mockClientConn{}, tt.txParams) + require.NoError(t, err) + require.NotNil(t, f) + err = f.calculateGas(tt.msgs...) + if tt.error { + require.Error(t, err) + } else { + require.NoError(t, err) + require.NotZero(t, f.txParams.GasConfig) + } + }) + } +} + +func TestFactory_Simulate(t *testing.T) { + tests := []struct { + name string + txParams TxParameters + msgs []transaction.Msg + error bool + }{ + { + name: "no error", + txParams: TxParameters{ + chainID: "demo", + AccountConfig: AccountConfig{ + address: addr, + }, + GasConfig: GasConfig{ + gasAdjustment: 1, + }, + }, + msgs: []transaction.Msg{ + &countertypes.MsgIncreaseCounter{ + Signer: signer, + Count: 0, + }, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + f, err := NewFactory(keybase, cdc, mockAccountRetriever{}, txConf, ac, mockClientConn{}, tt.txParams) + require.NoError(t, err) + require.NotNil(t, f) + got, got1, err := f.Simulate(tt.msgs...) + if tt.error { + require.Error(t, err) + } else { + require.NoError(t, err) + require.NotNil(t, got) + require.NotZero(t, got1) + } + }) + } +} + +func TestFactory_BuildSimTx(t *testing.T) { + tests := []struct { + name string + txParams TxParameters + msgs []transaction.Msg + want []byte + error bool + }{ + { + name: "no error", + txParams: TxParameters{ + chainID: "demo", + AccountConfig: AccountConfig{ + address: addr, + }, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + f, err := NewFactory(keybase, cdc, mockAccountRetriever{}, txConf, ac, mockClientConn{}, tt.txParams) + require.NoError(t, err) + require.NotNil(t, f) + got, err := f.BuildSimTx(tt.msgs...) + if tt.error { + require.Error(t, err) + } else { + require.NoError(t, err) + require.NotNil(t, got) + } + }) + } +} + +func TestFactory_Sign(t *testing.T) { + tests := []struct { + name string + txParams TxParameters + wantErr bool + }{ + { + name: "no error", + txParams: TxParameters{ + chainID: "demo", + AccountConfig: AccountConfig{ + fromName: "alice", + address: addr, + }, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + f, err := NewFactory(setKeyring(), cdc, mockAccountRetriever{}, txConf, ac, mockClientConn{}, tt.txParams) + require.NoError(t, err) + require.NotNil(t, f) + + err = f.BuildUnsignedTx([]transaction.Msg{ + &countertypes.MsgIncreaseCounter{ + Signer: signer, + Count: 0, + }, + }...) + require.NoError(t, err) + + require.Nil(t, f.tx.signatures) + require.Nil(t, f.tx.signerInfos) + + tx, err := f.sign(context.Background(), true) + if tt.wantErr { + require.Error(t, err) + } else { + require.NoError(t, err) + sigs, err := tx.GetSignatures() + require.NoError(t, err) + require.NotNil(t, sigs) + require.NotNil(t, f.tx.signerInfos) + } + }) + } +} + +func TestFactory_getSignBytesAdapter(t *testing.T) { + tests := []struct { + name string + txParams TxParameters + error bool + }{ + { + name: "no error", + txParams: TxParameters{ + chainID: "demo", + signMode: apitxsigning.SignMode_SIGN_MODE_DIRECT, + AccountConfig: AccountConfig{ + address: addr, + }, + }, + }, + { + name: "signMode not specified", + txParams: TxParameters{ + chainID: "demo", + AccountConfig: AccountConfig{ + address: addr, + }, + }, + error: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + f, err := NewFactory(setKeyring(), cdc, mockAccountRetriever{}, txConf, ac, mockClientConn{}, tt.txParams) + require.NoError(t, err) + require.NotNil(t, f) + + err = f.BuildUnsignedTx([]transaction.Msg{ + &countertypes.MsgIncreaseCounter{ + Signer: signer, + Count: 0, + }, + }...) + require.NoError(t, err) + + pk, err := f.keybase.GetPubKey("alice") + require.NoError(t, err) + require.NotNil(t, pk) + + addr, err := f.ac.BytesToString(pk.Address()) + require.NoError(t, err) + require.NotNil(t, addr) + + signerData := signing.SignerData{ + Address: addr, + ChainID: f.txParams.chainID, + AccountNumber: 0, + Sequence: 0, + PubKey: &anypb.Any{ + TypeUrl: codectypes.MsgTypeURL(pk), + Value: pk.Bytes(), + }, + } + + got, err := f.getSignBytesAdapter(context.Background(), signerData) + if tt.error { + require.Error(t, err) + } else { + require.NoError(t, err) + require.NotNil(t, got) + } + }) + } +} + +func Test_validateMemo(t *testing.T) { + tests := []struct { + name string + memo string + wantErr bool + }{ + { + name: "empty memo", + memo: "", + }, + { + name: "valid memo", + memo: "11245", + }, + { + name: "invalid Memo", + memo: "echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo", + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := validateMemo(tt.memo); (err != nil) != tt.wantErr { + t.Errorf("validateMemo() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} + +func TestFactory_WithFunctions(t *testing.T) { + tests := []struct { + name string + txParams TxParameters + withFunc func(*Factory) + checkFunc func(*Factory) bool + }{ + { + name: "with gas", + txParams: TxParameters{ + AccountConfig: AccountConfig{ + address: addr, + }, + }, + withFunc: func(f *Factory) { + f.WithGas(1000) + }, + checkFunc: func(f *Factory) bool { + return f.txParams.GasConfig.gas == 1000 + }, + }, + { + name: "with sequence", + txParams: TxParameters{ + AccountConfig: AccountConfig{ + address: addr, + }, + }, + withFunc: func(f *Factory) { + f.WithSequence(10) + }, + checkFunc: func(f *Factory) bool { + return f.txParams.AccountConfig.sequence == 10 + }, + }, + { + name: "with account number", + txParams: TxParameters{ + AccountConfig: AccountConfig{ + address: addr, + }, + }, + withFunc: func(f *Factory) { + f.WithAccountNumber(123) + }, + checkFunc: func(f *Factory) bool { + return f.txParams.AccountConfig.accountNumber == 123 + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + f, err := NewFactory(setKeyring(), cdc, mockAccountRetriever{}, txConf, ac, mockClientConn{}, tt.txParams) + require.NoError(t, err) + require.NotNil(t, f) + + tt.withFunc(&f) + require.True(t, tt.checkFunc(&f)) + }) + } +} + +func TestFactory_getTx(t *testing.T) { + tests := []struct { + name string + txSetter func(f *Factory) + checkResult func(Tx) + }{ + { + name: "empty tx", + txSetter: func(f *Factory) { + }, + checkResult: func(tx Tx) { + wTx, ok := tx.(*wrappedTx) + require.True(t, ok) + // require.Equal(t, []*anypb.Any(nil), wTx.Tx.Body.Messages) + require.Nil(t, wTx.Tx.Body.Messages) + require.Empty(t, wTx.Tx.Body.Memo) + require.Equal(t, uint64(0), wTx.Tx.Body.TimeoutHeight) + require.Equal(t, wTx.Tx.Body.Unordered, false) + require.Nil(t, wTx.Tx.Body.ExtensionOptions) + require.Nil(t, wTx.Tx.Body.NonCriticalExtensionOptions) + + require.Nil(t, wTx.Tx.AuthInfo.SignerInfos) + require.Nil(t, wTx.Tx.AuthInfo.Fee.Amount) + require.Equal(t, uint64(0), wTx.Tx.AuthInfo.Fee.GasLimit) + require.Empty(t, wTx.Tx.AuthInfo.Fee.Payer) + require.Empty(t, wTx.Tx.AuthInfo.Fee.Granter) + + require.Nil(t, wTx.Tx.Signatures) + }, + }, + { + name: "full tx", + txSetter: func(f *Factory) { + pk := secp256k1.GenPrivKey().PubKey() + addr, _ := f.ac.BytesToString(pk.Address()) + + f.tx.msgs = []transaction.Msg{&countertypes.MsgIncreaseCounter{ + Signer: addr, + Count: 0, + }} + + err := f.setFeePayer(addr) + require.NoError(t, err) + + f.tx.fees = []*base.Coin{{ + Denom: "cosmos", + Amount: "1000", + }} + + err = f.setSignatures([]Signature{{ + PubKey: pk, + Data: &SingleSignatureData{ + SignMode: apitxsigning.SignMode_SIGN_MODE_DIRECT, + Signature: nil, + }, + Sequence: 0, + }}...) + require.NoError(t, err) + }, + checkResult: func(tx Tx) { + wTx, ok := tx.(*wrappedTx) + require.True(t, ok) + require.True(t, len(wTx.Tx.Body.Messages) == 1) + + require.NotNil(t, wTx.Tx.AuthInfo.SignerInfos) + require.NotNil(t, wTx.Tx.AuthInfo.Fee.Amount) + + require.NotNil(t, wTx.Tx.Signatures) + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + f, err := NewFactory(keybase, cdc, mockAccountRetriever{}, txConf, ac, mockClientConn{}, TxParameters{}) + require.NoError(t, err) + tt.txSetter(&f) + got, err := f.getTx() + require.NoError(t, err) + require.NotNil(t, got) + tt.checkResult(got) + }) + } +} + +func TestFactory_getFee(t *testing.T) { + tests := []struct { + name string + feeAmount []*base.Coin + feeGranter string + feePayer string + }{ + { + name: "get fee with payer", + feeAmount: []*base.Coin{ + { + Denom: "cosmos", + Amount: "1000", + }, + }, + feeGranter: "", + feePayer: "cosmos1zglwfu6xjzvzagqcmvzewyzjp9xwqw5qwrr8n9", + }, + { + name: "get fee with granter", + feeAmount: []*base.Coin{ + { + Denom: "cosmos", + Amount: "1000", + }, + }, + feeGranter: "cosmos1zglwfu6xjzvzagqcmvzewyzjp9xwqw5qwrr8n9", + feePayer: "", + }, + { + name: "get fee with granter and granter", + feeAmount: []*base.Coin{ + { + Denom: "cosmos", + Amount: "1000", + }, + }, + feeGranter: "cosmos1zglwfu6xjzvzagqcmvzewyzjp9xwqw5qwrr8n9", + feePayer: "cosmos1zglwfu6xjzvzagqcmvzewyzjp9xwqw5qwrr8n9", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + f, err := NewFactory(keybase, cdc, mockAccountRetriever{}, txConf, ac, mockClientConn{}, TxParameters{}) + require.NoError(t, err) + f.tx.fees = tt.feeAmount + err = f.setFeeGranter(tt.feeGranter) + require.NoError(t, err) + err = f.setFeePayer(tt.feePayer) + require.NoError(t, err) + + fee, err := f.getFee() + require.NoError(t, err) + require.NotNil(t, fee) + + require.Equal(t, fee.Amount, tt.feeAmount) + require.Equal(t, fee.Granter, tt.feeGranter) + require.Equal(t, fee.Payer, tt.feePayer) + }) + } +} + +func TestFactory_getSigningTxData(t *testing.T) { + tests := []struct { + name string + txSetter func(f *Factory) + }{ + { + name: "empty tx", + txSetter: func(f *Factory) {}, + }, + { + name: "full tx", + txSetter: func(f *Factory) { + pk := secp256k1.GenPrivKey().PubKey() + addr, _ := ac.BytesToString(pk.Address()) + + f.tx.msgs = []transaction.Msg{&countertypes.MsgIncreaseCounter{ + Signer: addr, + Count: 0, + }} + + err := f.setFeePayer(addr) + require.NoError(t, err) + + f.tx.fees = []*base.Coin{{ + Denom: "cosmos", + Amount: "1000", + }} + + err = f.setSignatures([]Signature{{ + PubKey: pk, + Data: &SingleSignatureData{ + SignMode: apitxsigning.SignMode_SIGN_MODE_DIRECT, + Signature: []byte("signature"), + }, + Sequence: 0, + }}...) + require.NoError(t, err) + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + f, err := NewFactory(keybase, cdc, mockAccountRetriever{}, txConf, ac, mockClientConn{}, TxParameters{}) + require.NoError(t, err) + tt.txSetter(&f) + got, err := f.getSigningTxData() + require.NoError(t, err) + require.NotNil(t, got) + }) + } +} + +func TestFactoryr_setMsgs(t *testing.T) { + tests := []struct { + name string + msgs []transaction.Msg + wantErr bool + }{ + { + name: "set msgs", + msgs: []transaction.Msg{ + &countertypes.MsgIncreaseCounter{ + Signer: "cosmos1zglwfu6xjzvzagqcmvzewyzjp9xwqw5qwrr8n9", + Count: 0, + }, + &countertypes.MsgIncreaseCounter{ + Signer: "cosmos1zglwfu6xjzvzagqcmvzewyzjp9xwqw5qwrr8n9", + Count: 1, + }, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + f, err := NewFactory(keybase, cdc, mockAccountRetriever{}, txConf, ac, mockClientConn{}, TxParameters{}) + require.NoError(t, err) + f.tx.msgs = tt.msgs + require.NoError(t, err) + require.Equal(t, len(tt.msgs), len(f.tx.msgs)) + + for i, msg := range tt.msgs { + require.Equal(t, msg, f.tx.msgs[i]) + } + }) + } +} + +func TestFactory_SetMemo(t *testing.T) { + tests := []struct { + name string + memo string + }{ + { + name: "set memo", + memo: "test", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + f, err := NewFactory(keybase, cdc, mockAccountRetriever{}, txConf, ac, mockClientConn{}, TxParameters{}) + require.NoError(t, err) + f.tx.memo = tt.memo + require.Equal(t, f.tx.memo, tt.memo) + }) + } +} + +func TestFactory_SetFeeAmount(t *testing.T) { + tests := []struct { + name string + coins []*base.Coin + }{ + { + name: "set coins", + coins: []*base.Coin{ + { + Denom: "cosmos", + Amount: "1000", + }, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + f, err := NewFactory(keybase, cdc, mockAccountRetriever{}, txConf, ac, mockClientConn{}, TxParameters{}) + require.NoError(t, err) + f.tx.fees = tt.coins + require.Equal(t, len(tt.coins), len(f.tx.fees)) + + for i, coin := range tt.coins { + require.Equal(t, coin.Amount, f.tx.fees[i].Amount) + } + }) + } +} + +func TestFactory_SetGasLimit(t *testing.T) { + tests := []struct { + name string + gasLimit uint64 + }{ + { + name: "set gas limit", + gasLimit: 1, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + f, err := NewFactory(keybase, cdc, mockAccountRetriever{}, txConf, ac, mockClientConn{}, TxParameters{}) + require.NoError(t, err) + f.tx.gasLimit = tt.gasLimit + require.Equal(t, f.tx.gasLimit, tt.gasLimit) + }) + } +} + +func TestFactory_SetUnordered(t *testing.T) { + tests := []struct { + name string + unordered bool + }{ + { + name: "unordered", + unordered: true, + }, + { + name: "not unordered", + unordered: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + f, err := NewFactory(keybase, cdc, mockAccountRetriever{}, txConf, ac, mockClientConn{}, TxParameters{}) + require.NoError(t, err) + f.tx.unordered = tt.unordered + require.Equal(t, f.tx.unordered, tt.unordered) + }) + } +} + +func TestFactory_setSignatures(t *testing.T) { + tests := []struct { + name string + signatures func() []Signature + }{ + { + name: "set empty single signature", + signatures: func() []Signature { + return []Signature{{ + PubKey: secp256k1.GenPrivKey().PubKey(), + Data: &SingleSignatureData{ + SignMode: apitxsigning.SignMode_SIGN_MODE_DIRECT, + Signature: nil, + }, + Sequence: 0, + }} + }, + }, + { + name: "set single signature", + signatures: func() []Signature { + return []Signature{{ + PubKey: secp256k1.GenPrivKey().PubKey(), + Data: &SingleSignatureData{ + SignMode: apitxsigning.SignMode_SIGN_MODE_DIRECT, + Signature: []byte("signature"), + }, + Sequence: 0, + }} + }, + }, + { + name: "set empty multi signature", + signatures: func() []Signature { + return []Signature{{ + PubKey: multisig.NewLegacyAminoPubKey(1, []cryptotypes.PubKey{secp256k1.GenPrivKey().PubKey()}), + Data: &MultiSignatureData{ + BitArray: nil, + Signatures: []SignatureData{ + &SingleSignatureData{ + SignMode: apitxsigning.SignMode_SIGN_MODE_DIRECT, + Signature: nil, + }, + }, + }, + Sequence: 0, + }} + }, + }, + { + name: "set multi signature", + signatures: func() []Signature { + return []Signature{{ + PubKey: multisig.NewLegacyAminoPubKey(1, []cryptotypes.PubKey{secp256k1.GenPrivKey().PubKey()}), + Data: &MultiSignatureData{ + BitArray: nil, + Signatures: []SignatureData{ + &SingleSignatureData{ + SignMode: apitxsigning.SignMode_SIGN_MODE_DIRECT, + Signature: []byte("signature"), + }, + }, + }, + Sequence: 0, + }} + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + cryptocodec.RegisterInterfaces(cdc.InterfaceRegistry()) + f, err := NewFactory(keybase, cdc, mockAccountRetriever{}, txConf, ac, mockClientConn{}, TxParameters{}) + require.NoError(t, err) + sigs := tt.signatures() + err = f.setSignatures(sigs...) + require.NoError(t, err) + tx, err := f.getTx() + require.NoError(t, err) + signatures, err := tx.GetSignatures() + require.NoError(t, err) + require.Equal(t, len(sigs), len(signatures)) + for i := range signatures { + require.Equal(t, sigs[i].PubKey, signatures[i].PubKey) + } + }) + } +} + +/////////////////////// + +func Test_msgsV1toAnyV2(t *testing.T) { + tests := []struct { + name string + msgs []transaction.Msg + }{ + { + name: "convert msgV1 to V2", + msgs: []transaction.Msg{ + &countertypes.MsgIncreaseCounter{ + Signer: "cosmos1zglwfu6xjzvzagqcmvzewyzjp9xwqw5qwrr8n9", + Count: 0, + }, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := msgsV1toAnyV2(tt.msgs) + require.NoError(t, err) + require.NotNil(t, got) + }) + } +} + +func Test_intoAnyV2(t *testing.T) { + tests := []struct { + name string + msgs []*codectypes.Any + }{ + { + name: "any to v2", + msgs: []*codectypes.Any{ + { + TypeUrl: "/random/msg", + Value: []byte("random message"), + }, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := intoAnyV2(tt.msgs) + require.NotNil(t, got) + require.Equal(t, len(got), len(tt.msgs)) + for i, msg := range got { + require.Equal(t, msg.TypeUrl, tt.msgs[i].TypeUrl) + require.Equal(t, msg.Value, tt.msgs[i].Value) + } + }) + } +} diff --git a/client/v2/tx/flags.go b/client/v2/tx/flags.go new file mode 100644 index 000000000000..6ef8584042f7 --- /dev/null +++ b/client/v2/tx/flags.go @@ -0,0 +1,52 @@ +package tx + +import ( + "fmt" + "strconv" +) + +// Flag constants for transaction-related flags +const ( + defaultGasLimit = 200000 + gasFlagAuto = "auto" + + flagTimeoutTimestamp = "timeout-timestamp" + flagChainID = "chain-id" + flagNote = "note" + flagSignMode = "sign-mode" + flagAccountNumber = "account-number" + flagSequence = "sequence" + flagFrom = "from" + flagDryRun = "dry-run" + flagGas = "gas" + flagGasAdjustment = "gas-adjustment" + flagGasPrices = "gas-prices" + flagFees = "fees" + flagFeePayer = "fee-payer" + flagFeeGranter = "fee-granter" + flagUnordered = "unordered" + flagOffline = "offline" + flagGenerateOnly = "generate-only" +) + +// parseGasSetting parses a string gas value. The value may either be 'auto', +// which indicates a transaction should be executed in simulate mode to +// automatically find a sufficient gas value, or a string integer. It returns an +// error if a string integer is provided which cannot be parsed. +func parseGasSetting(gasStr string) (bool, uint64, error) { + switch gasStr { + case "": + return false, defaultGasLimit, nil + + case gasFlagAuto: + return true, 0, nil + + default: + gas, err := strconv.ParseUint(gasStr, 10, 64) + if err != nil { + return false, 0, fmt.Errorf("gas must be either integer or %s", gasFlagAuto) + } + + return false, gas, nil + } +} diff --git a/client/v2/tx/signature.go b/client/v2/tx/signature.go new file mode 100644 index 000000000000..66235380072b --- /dev/null +++ b/client/v2/tx/signature.go @@ -0,0 +1,197 @@ +package tx + +import ( + "errors" + "fmt" + + apicrypto "cosmossdk.io/api/cosmos/crypto/multisig/v1beta1" + apitxsigning "cosmossdk.io/api/cosmos/tx/signing/v1beta1" + apitx "cosmossdk.io/api/cosmos/tx/v1beta1" + + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" +) + +// Signature holds the necessary components to verify transaction signatures. +type Signature struct { + PubKey cryptotypes.PubKey // Public key for signature verification. + Data SignatureData // Signature data containing the actual signatures. + Sequence uint64 // Account sequence, relevant for SIGN_MODE_DIRECT. +} + +// SignatureData defines an interface for different signature data types. +type SignatureData interface { + isSignatureData() +} + +// SingleSignatureData stores a single signer's signature and its mode. +type SingleSignatureData struct { + SignMode apitxsigning.SignMode // Mode of the signature. + Signature []byte // Actual binary signature. +} + +// MultiSignatureData encapsulates signatures from a multisig transaction. +type MultiSignatureData struct { + BitArray *apicrypto.CompactBitArray // Bitmap of signers. + Signatures []SignatureData // Individual signatures. +} + +func (m *SingleSignatureData) isSignatureData() {} +func (m *MultiSignatureData) isSignatureData() {} + +// signatureDataToModeInfoAndSig converts SignatureData to ModeInfo and its corresponding raw signature. +func signatureDataToModeInfoAndSig(data SignatureData) (*apitx.ModeInfo, []byte) { + if data == nil { + return nil, nil + } + + switch data := data.(type) { + case *SingleSignatureData: + return &apitx.ModeInfo{ + Sum: &apitx.ModeInfo_Single_{ + Single: &apitx.ModeInfo_Single{Mode: data.SignMode}, + }, + }, data.Signature + case *MultiSignatureData: + modeInfos := make([]*apitx.ModeInfo, len(data.Signatures)) + sigs := make([][]byte, len(data.Signatures)) + + for i, d := range data.Signatures { + modeInfos[i], sigs[i] = signatureDataToModeInfoAndSig(d) + } + + multisig := cryptotypes.MultiSignature{Signatures: sigs} + sig, err := multisig.Marshal() + if err != nil { + panic(err) + } + + return &apitx.ModeInfo{ + Sum: &apitx.ModeInfo_Multi_{ + Multi: &apitx.ModeInfo_Multi{ + Bitarray: data.BitArray, + ModeInfos: modeInfos, + }, + }, + }, sig + default: + panic(fmt.Sprintf("unexpected signature data type %T", data)) + } +} + +// modeInfoAndSigToSignatureData converts ModeInfo and a raw signature to SignatureData. +func modeInfoAndSigToSignatureData(modeInfo *apitx.ModeInfo, sig []byte) (SignatureData, error) { + switch mi := modeInfo.Sum.(type) { + case *apitx.ModeInfo_Single_: + return &SingleSignatureData{ + SignMode: mi.Single.Mode, + Signature: sig, + }, nil + + case *apitx.ModeInfo_Multi_: + multi := mi.Multi + + sigs, err := decodeMultiSignatures(sig) + if err != nil { + return nil, err + } + + sigsV2 := make([]SignatureData, len(sigs)) + for i, mi := range multi.ModeInfos { + sigsV2[i], err = modeInfoAndSigToSignatureData(mi, sigs[i]) + if err != nil { + return nil, err + } + } + return &MultiSignatureData{ + BitArray: multi.Bitarray, + Signatures: sigsV2, + }, nil + } + + return nil, fmt.Errorf("unsupported ModeInfo type %T", modeInfo) +} + +// decodeMultiSignatures decodes a byte array into individual signatures. +func decodeMultiSignatures(bz []byte) ([][]byte, error) { + multisig := cryptotypes.MultiSignature{} + + err := multisig.Unmarshal(bz) + if err != nil { + return nil, err + } + + if len(multisig.XXX_unrecognized) > 0 { + return nil, errors.New("unrecognized fields in MultiSignature") + } + return multisig.Signatures, nil +} + +// signatureDataToProto converts a SignatureData interface to a protobuf SignatureDescriptor_Data. +// This function supports both SingleSignatureData and MultiSignatureData types. +// For SingleSignatureData, it directly maps the signature mode and signature bytes to the protobuf structure. +// For MultiSignatureData, it recursively converts each signature in the collection to the corresponding protobuf structure. +func signatureDataToProto(data SignatureData) (*apitxsigning.SignatureDescriptor_Data, error) { + switch data := data.(type) { + case *SingleSignatureData: + // Handle single signature data conversion. + return &apitxsigning.SignatureDescriptor_Data{ + Sum: &apitxsigning.SignatureDescriptor_Data_Single_{ + Single: &apitxsigning.SignatureDescriptor_Data_Single{ + Mode: data.SignMode, + Signature: data.Signature, + }, + }, + }, nil + case *MultiSignatureData: + var err error + descDatas := make([]*apitxsigning.SignatureDescriptor_Data, len(data.Signatures)) + + for i, j := range data.Signatures { + descDatas[i], err = signatureDataToProto(j) + if err != nil { + return nil, err + } + } + return &apitxsigning.SignatureDescriptor_Data{ + Sum: &apitxsigning.SignatureDescriptor_Data_Multi_{ + Multi: &apitxsigning.SignatureDescriptor_Data_Multi{ + Bitarray: data.BitArray, + Signatures: descDatas, + }, + }, + }, nil + } + + // Return an error if the data type is not supported. + return nil, fmt.Errorf("unexpected signature data type %T", data) +} + +// SignatureDataFromProto converts a protobuf SignatureDescriptor_Data to a SignatureData interface. +// This function supports both Single and Multi signature data types. +func SignatureDataFromProto(descData *apitxsigning.SignatureDescriptor_Data) (SignatureData, error) { + switch descData := descData.Sum.(type) { + case *apitxsigning.SignatureDescriptor_Data_Single_: + return &SingleSignatureData{ + SignMode: descData.Single.Mode, + Signature: descData.Single.Signature, + }, nil + case *apitxsigning.SignatureDescriptor_Data_Multi_: + var err error + multi := descData.Multi + data := make([]SignatureData, len(multi.Signatures)) + + for i, j := range multi.Signatures { + data[i], err = SignatureDataFromProto(j) + if err != nil { + return nil, err + } + } + + return &MultiSignatureData{ + BitArray: multi.Bitarray, + Signatures: data, + }, nil + } + + return nil, fmt.Errorf("unexpected signature data type %T", descData) +} diff --git a/client/v2/tx/signature_test.go b/client/v2/tx/signature_test.go new file mode 100644 index 000000000000..dd78add38d32 --- /dev/null +++ b/client/v2/tx/signature_test.go @@ -0,0 +1,143 @@ +package tx + +import ( + "reflect" + "testing" + + "github.com/stretchr/testify/require" + + apimultisig "cosmossdk.io/api/cosmos/crypto/multisig/v1beta1" + apisigning "cosmossdk.io/api/cosmos/tx/signing/v1beta1" + apitx "cosmossdk.io/api/cosmos/tx/v1beta1" +) + +func TestSignatureDataToModeInfoAndSig(t *testing.T) { + tests := []struct { + name string + data SignatureData + mIResult *apitx.ModeInfo + sigResult []byte + }{ + { + name: "single signature", + data: &SingleSignatureData{ + SignMode: apisigning.SignMode_SIGN_MODE_DIRECT, + Signature: []byte("signature"), + }, + mIResult: &apitx.ModeInfo{ + Sum: &apitx.ModeInfo_Single_{ + Single: &apitx.ModeInfo_Single{Mode: apisigning.SignMode_SIGN_MODE_DIRECT}, + }, + }, + sigResult: []byte("signature"), + }, + { + name: "multi signature", + data: &MultiSignatureData{ + BitArray: nil, + Signatures: []SignatureData{ + &SingleSignatureData{ + SignMode: apisigning.SignMode_SIGN_MODE_DIRECT, + Signature: []byte("signature"), + }, + }, + }, + mIResult: &apitx.ModeInfo{ + Sum: &apitx.ModeInfo_Multi_{ + Multi: &apitx.ModeInfo_Multi{ + Bitarray: nil, + ModeInfos: []*apitx.ModeInfo{ + { + Sum: &apitx.ModeInfo_Single_{ + Single: &apitx.ModeInfo_Single{Mode: apisigning.SignMode_SIGN_MODE_DIRECT}, + }, + }, + }, + }, + }, + }, + sigResult: []byte("\n\tsignature"), + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + modeInfo, signature := signatureDataToModeInfoAndSig(tt.data) + require.Equal(t, tt.mIResult, modeInfo) + require.Equal(t, tt.sigResult, signature) + }) + } +} + +func TestModeInfoAndSigToSignatureData(t *testing.T) { + type args struct { + modeInfo func() *apitx.ModeInfo + sig []byte + } + tests := []struct { + name string + args args + want SignatureData + wantErr bool + }{ + { + name: "to SingleSignatureData", + args: args{ + modeInfo: func() *apitx.ModeInfo { + return &apitx.ModeInfo{ + Sum: &apitx.ModeInfo_Single_{ + Single: &apitx.ModeInfo_Single{Mode: apisigning.SignMode_SIGN_MODE_DIRECT}, + }, + } + }, + sig: []byte("signature"), + }, + want: &SingleSignatureData{ + SignMode: apisigning.SignMode_SIGN_MODE_DIRECT, + Signature: []byte("signature"), + }, + }, + { + name: "to MultiSignatureData", + args: args{ + modeInfo: func() *apitx.ModeInfo { + return &apitx.ModeInfo{ + Sum: &apitx.ModeInfo_Multi_{ + Multi: &apitx.ModeInfo_Multi{ + Bitarray: &apimultisig.CompactBitArray{}, + ModeInfos: []*apitx.ModeInfo{ + { + Sum: &apitx.ModeInfo_Single_{ + Single: &apitx.ModeInfo_Single{Mode: apisigning.SignMode_SIGN_MODE_DIRECT}, + }, + }, + }, + }, + }, + } + }, + sig: []byte("\n\tsignature"), + }, + want: &MultiSignatureData{ // Changed from SingleSignatureData to MultiSignatureData + BitArray: &apimultisig.CompactBitArray{}, + Signatures: []SignatureData{ + &SingleSignatureData{ + SignMode: apisigning.SignMode_SIGN_MODE_DIRECT, + Signature: []byte("signature"), + }, + }, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := modeInfoAndSigToSignatureData(tt.args.modeInfo(), tt.args.sig) + if (err != nil) != tt.wantErr { + t.Errorf("ModeInfoAndSigToSignatureData() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("ModeInfoAndSigToSignatureData() got = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/client/v2/tx/tx.go b/client/v2/tx/tx.go new file mode 100644 index 000000000000..64e0199d8172 --- /dev/null +++ b/client/v2/tx/tx.go @@ -0,0 +1,229 @@ +package tx + +import ( + "bufio" + "errors" + "fmt" + "os" + + "github.com/cosmos/gogoproto/proto" + "github.com/spf13/pflag" + + apitxsigning "cosmossdk.io/api/cosmos/tx/signing/v1beta1" + "cosmossdk.io/client/v2/internal/account" + "cosmossdk.io/core/transaction" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/input" + "github.com/cosmos/cosmos-sdk/crypto/keyring" +) + +// GenerateOrBroadcastTxCLI will either generate and print an unsigned transaction +// or sign it and broadcast it returning an error upon failure. +func GenerateOrBroadcastTxCLI(ctx client.Context, flagSet *pflag.FlagSet, msgs ...transaction.Msg) error { + if err := validateMessages(msgs...); err != nil { + return err + } + + txf, err := newFactory(ctx, flagSet) + if err != nil { + return err + } + + genOnly, _ := flagSet.GetBool(flagGenerateOnly) + if genOnly { + return generateOnly(ctx, txf, msgs...) + } + + isDryRun, _ := flagSet.GetBool(flagDryRun) + if isDryRun { + return dryRun(txf, msgs...) + } + + return BroadcastTx(ctx, txf, msgs...) +} + +// newFactory creates a new transaction Factory based on the provided context and flag set. +// It initializes a new CLI keyring, extracts transaction parameters from the flag set, +// configures transaction settings, and sets up an account retriever for the transaction Factory. +func newFactory(ctx client.Context, flagSet *pflag.FlagSet) (Factory, error) { + k, err := keyring.NewAutoCLIKeyring(ctx.Keyring, ctx.AddressCodec) + if err != nil { + return Factory{}, err + } + + txConfig, err := NewTxConfig(ConfigOptions{ + AddressCodec: ctx.AddressCodec, + Cdc: ctx.Codec, + ValidatorAddressCodec: ctx.ValidatorAddressCodec, + EnablesSignModes: ctx.TxConfig.SignModeHandler().SupportedModes(), + }) + if err != nil { + return Factory{}, err + } + + accRetriever := account.NewAccountRetriever(ctx.AddressCodec, ctx, ctx.InterfaceRegistry) + + txf, err := NewFactoryFromFlagSet(flagSet, k, ctx.Codec, accRetriever, txConfig, ctx.AddressCodec, ctx) + if err != nil { + return Factory{}, err + } + + return txf, nil +} + +// validateMessages validates all msgs before generating or broadcasting the tx. +// We were calling ValidateBasic separately in each CLI handler before. +// Right now, we're factorizing that call inside this function. +// ref: https://github.com/cosmos/cosmos-sdk/pull/9236#discussion_r623803504 +func validateMessages(msgs ...transaction.Msg) error { + for _, msg := range msgs { + m, ok := msg.(HasValidateBasic) + if !ok { + continue + } + + if err := m.ValidateBasic(); err != nil { + return err + } + } + + return nil +} + +// generateOnly prepares the transaction and prints the unsigned transaction string. +// It first calls Prepare on the transaction factory to set up any necessary pre-conditions. +// If preparation is successful, it generates an unsigned transaction string using the provided messages. +func generateOnly(ctx client.Context, txf Factory, msgs ...transaction.Msg) error { + uTx, err := txf.UnsignedTxString(msgs...) + if err != nil { + return err + } + + return ctx.PrintString(uTx) +} + +// dryRun performs a dry run of the transaction to estimate the gas required. +// It prepares the transaction factory and simulates the transaction with the provided messages. +func dryRun(txf Factory, msgs ...transaction.Msg) error { + _, gas, err := txf.Simulate(msgs...) + if err != nil { + return err + } + + _, err = fmt.Fprintf(os.Stderr, "%s\n", GasEstimateResponse{GasEstimate: gas}) + return err +} + +// SimulateTx simulates a tx and returns the simulation response obtained by the query. +func SimulateTx(ctx client.Context, flagSet *pflag.FlagSet, msgs ...transaction.Msg) (proto.Message, error) { + txf, err := newFactory(ctx, flagSet) + if err != nil { + return nil, err + } + + simulation, _, err := txf.Simulate(msgs...) + return simulation, err +} + +// BroadcastTx attempts to generate, sign and broadcast a transaction with the +// given set of messages. It will also simulate gas requirements if necessary. +// It will return an error upon failure. +func BroadcastTx(clientCtx client.Context, txf Factory, msgs ...transaction.Msg) error { + if txf.simulateAndExecute() { + err := txf.calculateGas(msgs...) + if err != nil { + return err + } + } + + err := txf.BuildUnsignedTx(msgs...) + if err != nil { + return err + } + + if !clientCtx.SkipConfirm { + encoder := txf.txConfig.TxJSONEncoder() + if encoder == nil { + return errors.New("failed to encode transaction: tx json encoder is nil") + } + + unsigTx, err := txf.getTx() + if err != nil { + return err + } + txBytes, err := encoder(unsigTx) + if err != nil { + return fmt.Errorf("failed to encode transaction: %w", err) + } + + if err := clientCtx.PrintRaw(txBytes); err != nil { + _, _ = fmt.Fprintf(os.Stderr, "error: %v\n%s\n", err, txBytes) + } + + buf := bufio.NewReader(os.Stdin) + ok, err := input.GetConfirmation("confirm transaction before signing and broadcasting", buf, os.Stderr) + if err != nil { + _, _ = fmt.Fprintf(os.Stderr, "error: %v\ncanceled transaction\n", err) + return err + } + if !ok { + _, _ = fmt.Fprintln(os.Stderr, "canceled transaction") + return nil + } + } + + signedTx, err := txf.sign(clientCtx.CmdContext, true) + if err != nil { + return err + } + + txBytes, err := txf.txConfig.TxEncoder()(signedTx) + if err != nil { + return err + } + + // broadcast to a CometBFT node + res, err := clientCtx.BroadcastTx(txBytes) + if err != nil { + return err + } + + return clientCtx.PrintProto(res) +} + +// countDirectSigners counts the number of DIRECT signers in a signature data. +func countDirectSigners(sigData SignatureData) int { + switch data := sigData.(type) { + case *SingleSignatureData: + if data.SignMode == apitxsigning.SignMode_SIGN_MODE_DIRECT { + return 1 + } + + return 0 + case *MultiSignatureData: + directSigners := 0 + for _, d := range data.Signatures { + directSigners += countDirectSigners(d) + } + + return directSigners + default: + panic("unreachable case") + } +} + +// getSignMode returns the corresponding apitxsigning.SignMode based on the provided mode string. +func getSignMode(mode string) apitxsigning.SignMode { + switch mode { + case "direct": + return apitxsigning.SignMode_SIGN_MODE_DIRECT + case "direct-aux": + return apitxsigning.SignMode_SIGN_MODE_DIRECT_AUX + case "amino-json": + return apitxsigning.SignMode_SIGN_MODE_LEGACY_AMINO_JSON + case "textual": + return apitxsigning.SignMode_SIGN_MODE_TEXTUAL + } + return apitxsigning.SignMode_SIGN_MODE_UNSPECIFIED +} diff --git a/client/v2/tx/types.go b/client/v2/tx/types.go new file mode 100644 index 000000000000..ee60c27065b6 --- /dev/null +++ b/client/v2/tx/types.go @@ -0,0 +1,214 @@ +package tx + +import ( + "fmt" + "time" + + "github.com/spf13/pflag" + "google.golang.org/protobuf/types/known/anypb" + + base "cosmossdk.io/api/cosmos/base/v1beta1" + apitxsigning "cosmossdk.io/api/cosmos/tx/signing/v1beta1" + apitx "cosmossdk.io/api/cosmos/tx/v1beta1" + keyring2 "cosmossdk.io/client/v2/autocli/keyring" + "cosmossdk.io/client/v2/internal/coins" + "cosmossdk.io/core/address" + "cosmossdk.io/core/transaction" + + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" +) + +// HasValidateBasic is a copy of types.HasValidateBasic to avoid sdk import. +type HasValidateBasic interface { + // ValidateBasic does a simple validation check that + // doesn't require access to any other information. + ValidateBasic() error +} + +// TxParameters defines the parameters required for constructing a transaction. +type TxParameters struct { + timeoutTimestamp time.Time // timeoutTimestamp indicates a timestamp after which the transaction is no longer valid. + chainID string // chainID specifies the unique identifier of the blockchain where the transaction will be processed. + memo string // memo contains any arbitrary memo to be attached to the transaction. + signMode apitxsigning.SignMode // signMode determines the signing mode to be used for the transaction. + + AccountConfig // AccountConfig includes information about the transaction originator's account. + GasConfig // GasConfig specifies the gas settings for the transaction. + FeeConfig // FeeConfig details the fee associated with the transaction. + ExecutionOptions // ExecutionOptions includes settings that modify how the transaction is executed. +} + +// AccountConfig defines the 'account' related fields in a transaction. +type AccountConfig struct { + // accountNumber is the unique identifier for the account. + accountNumber uint64 + // sequence is the sequence number of the transaction. + sequence uint64 + // fromName is the name of the account sending the transaction. + fromName string + // fromAddress is the address of the account sending the transaction. + fromAddress string + // address is the byte representation of the account address. + address []byte +} + +// GasConfig defines the 'gas' related fields in a transaction. +// GasConfig defines the gas-related settings for a transaction. +type GasConfig struct { + gas uint64 // gas is the amount of gas requested for the transaction. + gasAdjustment float64 // gasAdjustment is the factor by which the estimated gas is multiplied to calculate the final gas limit. + gasPrices []*base.DecCoin // gasPrices is a list of denominations of DecCoin used to calculate the fee paid for the gas. +} + +// NewGasConfig creates a new GasConfig with the specified gas, gasAdjustment, and gasPrices. +// If the provided gas value is zero, it defaults to a predefined value (defaultGas). +// The gasPrices string is parsed into a slice of DecCoin. +func NewGasConfig(gas uint64, gasAdjustment float64, gasPrices string) (GasConfig, error) { + parsedGasPrices, err := coins.ParseDecCoins(gasPrices) + if err != nil { + return GasConfig{}, err + } + + return GasConfig{ + gas: gas, + gasAdjustment: gasAdjustment, + gasPrices: parsedGasPrices, + }, nil +} + +// FeeConfig holds the fee details for a transaction. +type FeeConfig struct { + fees []*base.Coin // fees are the amounts paid for the transaction. + feePayer string // feePayer is the account responsible for paying the fees. + feeGranter string // feeGranter is the account granting the fee payment if different from the payer. +} + +// NewFeeConfig creates a new FeeConfig with the specified fees, feePayer, and feeGranter. +// It parses the fees string into a slice of Coin, handling normalization. +func NewFeeConfig(fees, feePayer, feeGranter string) (FeeConfig, error) { + parsedFees, err := coins.ParseCoinsNormalized(fees) + if err != nil { + return FeeConfig{}, err + } + + return FeeConfig{ + fees: parsedFees, + feePayer: feePayer, + feeGranter: feeGranter, + }, nil +} + +// ExecutionOptions defines the transaction execution options ran by the client +type ExecutionOptions struct { + unordered bool // unordered indicates if the transaction execution order is not guaranteed. + simulateAndExecute bool // simulateAndExecute indicates if the transaction should be simulated before execution. +} + +// GasEstimateResponse defines a response definition for tx gas estimation. +type GasEstimateResponse struct { + GasEstimate uint64 `json:"gas_estimate" yaml:"gas_estimate"` +} + +func (gr GasEstimateResponse) String() string { + return fmt.Sprintf("gas estimate: %d", gr.GasEstimate) +} + +// txState represents the internal state of a transaction. +type txState struct { + msgs []transaction.Msg + timeoutHeight uint64 + timeoutTimestamp time.Time + granter []byte + payer []byte + unordered bool + memo string + gasLimit uint64 + fees []*base.Coin + signerInfos []*apitx.SignerInfo + signatures [][]byte + + extensionOptions []*anypb.Any + nonCriticalExtensionOptions []*anypb.Any +} + +// Tx defines the interface for transaction operations. +type Tx interface { + transaction.Tx + + // GetSigners fetches the addresses of the signers of the transaction. + GetSigners() ([][]byte, error) + // GetPubKeys retrieves the public keys of the signers of the transaction. + GetPubKeys() ([]cryptotypes.PubKey, error) + // GetSignatures fetches the signatures attached to the transaction. + GetSignatures() ([]Signature, error) +} + +// txParamsFromFlagSet extracts the transaction parameters from the provided FlagSet. +func txParamsFromFlagSet(flags *pflag.FlagSet, keybase keyring2.Keyring, ac address.Codec) (params TxParameters, err error) { + timestampUnix, _ := flags.GetInt64(flagTimeoutTimestamp) + timeoutTimestamp := time.Unix(timestampUnix, 0) + chainID, _ := flags.GetString(flagChainID) + memo, _ := flags.GetString(flagNote) + signMode, _ := flags.GetString(flagSignMode) + + accNumber, _ := flags.GetUint64(flagAccountNumber) + sequence, _ := flags.GetUint64(flagSequence) + from, _ := flags.GetString(flagFrom) + + var fromName, fromAddress string + var addr []byte + isDryRun, _ := flags.GetBool(flagDryRun) + if isDryRun { + addr, err = ac.StringToBytes(from) + } else { + fromName, fromAddress, _, err = keybase.KeyInfo(from) + if err == nil { + addr, err = ac.StringToBytes(fromAddress) + } + } + if err != nil { + return params, err + } + + gas, _ := flags.GetString(flagGas) + simulate, gasValue, _ := parseGasSetting(gas) + gasAdjustment, _ := flags.GetFloat64(flagGasAdjustment) + gasPrices, _ := flags.GetString(flagGasPrices) + + fees, _ := flags.GetString(flagFees) + feePayer, _ := flags.GetString(flagFeePayer) + feeGrater, _ := flags.GetString(flagFeeGranter) + + unordered, _ := flags.GetBool(flagUnordered) + + gasConfig, err := NewGasConfig(gasValue, gasAdjustment, gasPrices) + if err != nil { + return params, err + } + feeConfig, err := NewFeeConfig(fees, feePayer, feeGrater) + if err != nil { + return params, err + } + + txParams := TxParameters{ + timeoutTimestamp: timeoutTimestamp, + chainID: chainID, + memo: memo, + signMode: getSignMode(signMode), + AccountConfig: AccountConfig{ + accountNumber: accNumber, + sequence: sequence, + fromName: fromName, + fromAddress: fromAddress, + address: addr, + }, + GasConfig: gasConfig, + FeeConfig: feeConfig, + ExecutionOptions: ExecutionOptions{ + unordered: unordered, + simulateAndExecute: simulate, + }, + } + + return txParams, nil +} diff --git a/client/v2/tx/wrapper.go b/client/v2/tx/wrapper.go new file mode 100644 index 000000000000..fbcf62126bfc --- /dev/null +++ b/client/v2/tx/wrapper.go @@ -0,0 +1,115 @@ +package tx + +import ( + "fmt" + "reflect" + "strings" + + "github.com/cosmos/gogoproto/proto" + "google.golang.org/protobuf/types/known/anypb" + + "cosmossdk.io/core/transaction" + "cosmossdk.io/x/tx/decode" + + "github.com/cosmos/cosmos-sdk/codec" + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" +) + +var ( + _ transaction.Tx = wrappedTx{} + _ Tx = wrappedTx{} +) + +// wrappedTx wraps a transaction and provides a codec for binary encoding/decoding. +type wrappedTx struct { + *decode.DecodedTx + + cdc codec.BinaryCodec +} + +func newWrapperTx(cdc codec.BinaryCodec, decodedTx *decode.DecodedTx) *wrappedTx { + return &wrappedTx{ + DecodedTx: decodedTx, + cdc: cdc, + } +} + +// GetSigners fetches the addresses of the signers of the transaction. +func (w wrappedTx) GetSigners() ([][]byte, error) { + return w.Signers, nil +} + +// GetPubKeys retrieves the public keys of the signers from the transaction's SignerInfos. +func (w wrappedTx) GetPubKeys() ([]cryptotypes.PubKey, error) { + signerInfos := w.Tx.AuthInfo.SignerInfos + pks := make([]cryptotypes.PubKey, len(signerInfos)) + + for i, si := range signerInfos { + // NOTE: it is okay to leave this nil if there is no PubKey in the SignerInfo. + // PubKey's can be left unset in SignerInfo. + if si.PublicKey == nil { + continue + } + maybePk, err := w.decodeAny(si.PublicKey) + if err != nil { + return nil, err + } + pk, ok := maybePk.(cryptotypes.PubKey) + if !ok { + return nil, fmt.Errorf("invalid public key type: %T", maybePk) + } + pks[i] = pk + } + + return pks, nil +} + +// GetSignatures fetches the signatures attached to the transaction. +func (w wrappedTx) GetSignatures() ([]Signature, error) { + signerInfos := w.Tx.AuthInfo.SignerInfos + sigs := w.Tx.Signatures + + pubKeys, err := w.GetPubKeys() + if err != nil { + return nil, err + } + signatures := make([]Signature, len(sigs)) + + for i, si := range signerInfos { + if si.ModeInfo == nil || si.ModeInfo.Sum == nil { + signatures[i] = Signature{ + PubKey: pubKeys[i], + } + } else { + sigData, err := modeInfoAndSigToSignatureData(si.ModeInfo, sigs[i]) + if err != nil { + return nil, err + } + signatures[i] = Signature{ + PubKey: pubKeys[i], + Data: sigData, + Sequence: si.GetSequence(), + } + } + } + + return signatures, nil +} + +// decodeAny decodes a protobuf Any message into a concrete proto.Message. +func (w wrappedTx) decodeAny(anyPb *anypb.Any) (proto.Message, error) { + name := anyPb.GetTypeUrl() + if i := strings.LastIndexByte(name, '/'); i >= 0 { + name = name[i+len("/"):] + } + typ := proto.MessageType(name) + if typ == nil { + return nil, fmt.Errorf("unknown type: %s", name) + } + v1 := reflect.New(typ.Elem()).Interface().(proto.Message) + err := w.cdc.Unmarshal(anyPb.GetValue(), v1) + if err != nil { + return nil, err + } + return v1, nil +} diff --git a/codec/amino_codec_test.go b/codec/amino_codec_test.go index 63df85e83782..f15da6a1456b 100644 --- a/codec/amino_codec_test.go +++ b/codec/amino_codec_test.go @@ -71,8 +71,6 @@ func TestAminoCodecMarshalJSONIndent(t *testing.T) { } for _, tc := range testCases { - tc := tc - t.Run(tc.name, func(t *testing.T) { cdc := codec.NewAminoCodec(createTestCodec()) bz, err := cdc.MarshalJSONIndent(tc.input, "", " ") diff --git a/codec/codec_common_test.go b/codec/codec_common_test.go index 3280d2c195e3..4c0118f41994 100644 --- a/codec/codec_common_test.go +++ b/codec/codec_common_test.go @@ -122,7 +122,7 @@ func testMarshaling(t *testing.T, cdc interface { } for _, tc := range testCases { - tc := tc + m1 := mustMarshaler{cdc.Marshal, cdc.MustMarshal, cdc.Unmarshal, cdc.MustUnmarshal} m2 := mustMarshaler{cdc.MarshalLengthPrefixed, cdc.MustMarshalLengthPrefixed, cdc.UnmarshalLengthPrefixed, cdc.MustUnmarshalLengthPrefixed} m3 := mustMarshaler{ diff --git a/codec/unknownproto/unit_helpers_test.go b/codec/unknownproto/unit_helpers_test.go index 9c408a6d1f8a..b1564224892e 100644 --- a/codec/unknownproto/unit_helpers_test.go +++ b/codec/unknownproto/unit_helpers_test.go @@ -22,7 +22,6 @@ func TestWireTypeToString(t *testing.T) { } for _, tt := range tests { - tt := tt t.Run(fmt.Sprintf("wireType=%d", tt.typ), func(t *testing.T) { if g, w := wireTypeToString(tt.typ), tt.want; g != w { t.Fatalf("Mismatch:\nGot: %q\nWant: %q\n", g, w) diff --git a/codec/unknownproto/unknown_fields_test.go b/codec/unknownproto/unknown_fields_test.go index 7f2228e58436..85338f0595cb 100644 --- a/codec/unknownproto/unknown_fields_test.go +++ b/codec/unknownproto/unknown_fields_test.go @@ -223,7 +223,6 @@ func TestRejectUnknownFieldsRepeated(t *testing.T) { } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { protoBlob, err := proto.Marshal(tt.in) if err != nil { @@ -280,7 +279,6 @@ func TestRejectUnknownFields_allowUnknownNonCriticals(t *testing.T) { } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { blob, err := proto.Marshal(tt.in) if err != nil { @@ -483,7 +481,6 @@ func TestRejectUnknownFieldsNested(t *testing.T) { } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { protoBlob, err := proto.Marshal(tt.in) if err != nil { @@ -634,7 +631,6 @@ func TestRejectUnknownFieldsFlat(t *testing.T) { } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { blob, err := proto.Marshal(tt.in) if err != nil { diff --git a/collections/CHANGELOG.md b/collections/CHANGELOG.md index 6be747f2f4b2..d0da0dcfa533 100644 --- a/collections/CHANGELOG.md +++ b/collections/CHANGELOG.md @@ -39,6 +39,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ * [#19861](https://github.com/cosmos/cosmos-sdk/pull/19861) Add `NewJSONValueCodec` value codec as an alternative for `codec.CollValue` from the SDK for non protobuf types. * [#21090](https://github.com/cosmos/cosmos-sdk/pull/21090) Introduces `Quad`, a composite key with four keys. * [#20704](https://github.com/cosmos/cosmos-sdk/pull/20704) Add `ModuleCodec` method to `Schema` and `HasSchemaCodec` interface in order to support `cosmossdk.io/schema` compatible indexing. +* [#20538](https://github.com/cosmos/cosmos-sdk/pull/20538) Add `Nameable` variations to `KeyCodec` and `ValueCodec` to allow for better indexing of `collections` types. ## [v0.4.0](https://github.com/cosmos/cosmos-sdk/releases/tag/collections%2Fv0.4.0) diff --git a/collections/codec/bool.go b/collections/codec/bool.go index 827af36c0715..8278def71185 100644 --- a/collections/codec/bool.go +++ b/collections/codec/bool.go @@ -6,7 +6,7 @@ import ( "strconv" ) -func NewBoolKey[T ~bool]() KeyCodec[T] { return boolKey[T]{} } +func NewBoolKey[T ~bool]() NameableKeyCodec[T] { return boolKey[T]{} } type boolKey[T ~bool] struct{} @@ -64,3 +64,7 @@ func (b boolKey[T]) DecodeNonTerminal(buffer []byte) (int, T, error) { func (b boolKey[T]) SizeNonTerminal(key T) int { return b.Size(key) } + +func (b boolKey[T]) WithName(name string) KeyCodec[T] { + return NamedKeyCodec[T]{KeyCodec: b, Name: name} +} diff --git a/collections/codec/bytes.go b/collections/codec/bytes.go index 28334795e365..0fb056782c05 100644 --- a/collections/codec/bytes.go +++ b/collections/codec/bytes.go @@ -10,7 +10,7 @@ import ( // using the BytesKey KeyCodec. const MaxBytesKeyNonTerminalSize = math.MaxUint8 -func NewBytesKey[T ~[]byte]() KeyCodec[T] { return bytesKey[T]{} } +func NewBytesKey[T ~[]byte]() NameableKeyCodec[T] { return bytesKey[T]{} } type bytesKey[T ~[]byte] struct{} @@ -77,3 +77,7 @@ func (bytesKey[T]) DecodeNonTerminal(buffer []byte) (int, T, error) { func (bytesKey[T]) SizeNonTerminal(key T) int { return len(key) + 1 } + +func (b bytesKey[T]) WithName(name string) KeyCodec[T] { + return NamedKeyCodec[T]{KeyCodec: b, Name: name} +} diff --git a/collections/codec/codec.go b/collections/codec/codec.go index 2988c9f52425..b8f5cf994613 100644 --- a/collections/codec/codec.go +++ b/collections/codec/codec.go @@ -125,7 +125,9 @@ type UntypedValueCodec struct { } // KeyToValueCodec converts a KeyCodec into a ValueCodec. -func KeyToValueCodec[K any](keyCodec KeyCodec[K]) ValueCodec[K] { return keyToValueCodec[K]{keyCodec} } +func KeyToValueCodec[K any](keyCodec KeyCodec[K]) NameableValueCodec[K] { + return keyToValueCodec[K]{kc: keyCodec} +} // keyToValueCodec is a ValueCodec that wraps a KeyCodec to make it behave like a ValueCodec. type keyToValueCodec[K any] struct { @@ -167,3 +169,7 @@ func (k keyToValueCodec[K]) Stringify(value K) string { func (k keyToValueCodec[K]) ValueType() string { return k.kc.KeyType() } + +func (k keyToValueCodec[K]) WithName(name string) ValueCodec[K] { + return NamedValueCodec[K]{ValueCodec: k, Name: name} +} diff --git a/collections/codec/codec_test.go b/collections/codec/codec_test.go index 16fd10553f41..65eb0704ee2d 100644 --- a/collections/codec/codec_test.go +++ b/collections/codec/codec_test.go @@ -7,7 +7,7 @@ import ( ) func TestUntypedValueCodec(t *testing.T) { - vc := NewUntypedValueCodec(KeyToValueCodec(NewStringKeyCodec[string]())) + vc := NewUntypedValueCodec(ValueCodec[string](KeyToValueCodec(KeyCodec[string](NewStringKeyCodec[string]())))) t.Run("encode/decode", func(t *testing.T) { _, err := vc.Encode(0) diff --git a/collections/codec/int.go b/collections/codec/int.go index 1300efde4df0..9fb2a824f2fd 100644 --- a/collections/codec/int.go +++ b/collections/codec/int.go @@ -7,7 +7,7 @@ import ( "strconv" ) -func NewInt64Key[T ~int64]() KeyCodec[T] { return int64Key[T]{} } +func NewInt64Key[T ~int64]() NameableKeyCodec[T] { return int64Key[T]{} } type int64Key[T ~int64] struct{} @@ -64,7 +64,11 @@ func (i int64Key[T]) SizeNonTerminal(_ T) int { return 8 } -func NewInt32Key[T ~int32]() KeyCodec[T] { +func (i int64Key[T]) WithName(name string) KeyCodec[T] { + return NamedKeyCodec[T]{KeyCodec: i, Name: name} +} + +func NewInt32Key[T ~int32]() NameableKeyCodec[T] { return int32Key[T]{} } @@ -121,3 +125,7 @@ func (i int32Key[T]) DecodeNonTerminal(buffer []byte) (int, T, error) { func (i int32Key[T]) SizeNonTerminal(_ T) int { return 4 } + +func (i int32Key[T]) WithName(name string) KeyCodec[T] { + return NamedKeyCodec[T]{KeyCodec: i, Name: name} +} diff --git a/collections/codec/naming.go b/collections/codec/naming.go new file mode 100644 index 000000000000..ffaeeae58db3 --- /dev/null +++ b/collections/codec/naming.go @@ -0,0 +1,63 @@ +package codec + +import "fmt" + +// NameableKeyCodec is a KeyCodec that can be named. +type NameableKeyCodec[T any] interface { + KeyCodec[T] + + // WithName returns the KeyCodec with the provided name. + WithName(name string) KeyCodec[T] +} + +// NameableValueCodec is a ValueCodec that can be named. +type NameableValueCodec[T any] interface { + ValueCodec[T] + + // WithName returns the ValueCodec with the provided name. + WithName(name string) ValueCodec[T] +} + +// NamedKeyCodec wraps a KeyCodec with a name. +// The underlying key codec MUST have exactly one field in its schema. +type NamedKeyCodec[T any] struct { + KeyCodec[T] + + // Name is the name of the KeyCodec in the schema. + Name string +} + +// SchemaCodec returns the schema codec for the named key codec. +func (n NamedKeyCodec[T]) SchemaCodec() (SchemaCodec[T], error) { + cdc, err := KeySchemaCodec[T](n.KeyCodec) + if err != nil { + return SchemaCodec[T]{}, err + } + return withName(cdc, n.Name) +} + +// NamedValueCodec wraps a ValueCodec with a name. +// The underlying value codec MUST have exactly one field in its schema. +type NamedValueCodec[T any] struct { + ValueCodec[T] + + // Name is the name of the ValueCodec in the schema. + Name string +} + +// SchemaCodec returns the schema codec for the named value codec. +func (n NamedValueCodec[T]) SchemaCodec() (SchemaCodec[T], error) { + cdc, err := ValueSchemaCodec[T](n.ValueCodec) + if err != nil { + return SchemaCodec[T]{}, err + } + return withName(cdc, n.Name) +} + +func withName[T any](cdc SchemaCodec[T], name string) (SchemaCodec[T], error) { + if len(cdc.Fields) != 1 { + return SchemaCodec[T]{}, fmt.Errorf("expected exactly one field to be named, got %d", len(cdc.Fields)) + } + cdc.Fields[0].Name = name + return cdc, nil +} diff --git a/collections/codec/string.go b/collections/codec/string.go index 3189b8bc9cbf..7b3cdf0faa1e 100644 --- a/collections/codec/string.go +++ b/collections/codec/string.go @@ -6,7 +6,7 @@ import ( "fmt" ) -func NewStringKeyCodec[T ~string]() KeyCodec[T] { return stringKey[T]{} } +func NewStringKeyCodec[T ~string]() NameableKeyCodec[T] { return stringKey[T]{} } const ( // StringDelimiter defines the delimiter of a string key when used in non-terminal encodings. @@ -66,3 +66,7 @@ func (stringKey[T]) Stringify(key T) string { func (stringKey[T]) KeyType() string { return "string" } + +func (s stringKey[T]) WithName(name string) KeyCodec[T] { + return NamedKeyCodec[T]{KeyCodec: s, Name: name} +} diff --git a/collections/codec/uint.go b/collections/codec/uint.go index 658235d385ad..83efa2ec6453 100644 --- a/collections/codec/uint.go +++ b/collections/codec/uint.go @@ -7,7 +7,7 @@ import ( "strconv" ) -func NewUint64Key[T ~uint64]() KeyCodec[T] { return uint64Key[T]{} } +func NewUint64Key[T ~uint64]() NameableKeyCodec[T] { return uint64Key[T]{} } type uint64Key[T ~uint64] struct{} @@ -55,7 +55,11 @@ func (uint64Key[T]) KeyType() string { return "uint64" } -func NewUint32Key[T ~uint32]() KeyCodec[T] { return uint32Key[T]{} } +func (u uint64Key[T]) WithName(name string) KeyCodec[T] { + return NamedKeyCodec[T]{KeyCodec: u, Name: name} +} + +func NewUint32Key[T ~uint32]() NameableKeyCodec[T] { return uint32Key[T]{} } type uint32Key[T ~uint32] struct{} @@ -95,7 +99,11 @@ func (u uint32Key[T]) DecodeNonTerminal(buffer []byte) (int, T, error) { return func (uint32Key[T]) SizeNonTerminal(_ T) int { return 4 } -func NewUint16Key[T ~uint16]() KeyCodec[T] { return uint16Key[T]{} } +func (u uint32Key[T]) WithName(name string) KeyCodec[T] { + return NamedKeyCodec[T]{KeyCodec: u, Name: name} +} + +func NewUint16Key[T ~uint16]() NameableKeyCodec[T] { return uint16Key[T]{} } type uint16Key[T ~uint16] struct{} @@ -135,6 +143,10 @@ func (u uint16Key[T]) DecodeNonTerminal(buffer []byte) (int, T, error) { return func (u uint16Key[T]) SizeNonTerminal(key T) int { return u.Size(key) } +func (u uint16Key[T]) WithName(name string) KeyCodec[T] { + return NamedKeyCodec[T]{KeyCodec: u, Name: name} +} + func uintEncodeJSON(value uint64) ([]byte, error) { str := `"` + strconv.FormatUint(value, 10) + `"` return []byte(str), nil diff --git a/collections/collections.go b/collections/collections.go index 10748e0bd935..2c67de4604aa 100644 --- a/collections/collections.go +++ b/collections/collections.go @@ -104,7 +104,7 @@ type Collection interface { // decoders and encoders to and from schema values and raw kv-store bytes. type collectionSchemaCodec struct { coll Collection - objectType schema.ObjectType + objectType schema.StateObjectType keyDecoder func([]byte) (any, error) valueDecoder func([]byte) (any, error) } diff --git a/collections/go.mod b/collections/go.mod index 3298820e8c12..e1d9dcef95d1 100644 --- a/collections/go.mod +++ b/collections/go.mod @@ -3,9 +3,9 @@ module cosmossdk.io/collections go 1.23 require ( - cosmossdk.io/core v1.0.0-alpha.2 - cosmossdk.io/core/testing v0.0.0-00010101000000-000000000000 - cosmossdk.io/schema v0.2.0 + cosmossdk.io/core v1.0.0-alpha.4 + cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29 + cosmossdk.io/schema v0.3.0 github.com/stretchr/testify v1.9.0 github.com/tidwall/btree v1.7.0 pgregory.net/rapid v1.1.0 @@ -16,5 +16,3 @@ require ( github.com/pmezard/go-difflib v1.0.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) - -replace cosmossdk.io/core/testing => ../core/testing diff --git a/collections/go.sum b/collections/go.sum index 15437b213853..ad552827598c 100644 --- a/collections/go.sum +++ b/collections/go.sum @@ -1,7 +1,9 @@ -cosmossdk.io/core v1.0.0-alpha.2 h1:epU0Xwces4Rgl5bMhHHkXGaGDcyucNGlC/JDH+Suckg= -cosmossdk.io/core v1.0.0-alpha.2/go.mod h1:abgLjeFLhtuKIYZWSPlVUgQBrKObO7ULV35KYfexE90= -cosmossdk.io/schema v0.2.0 h1:UH5CR1DqUq8yP+5Np8PbvG4YX0zAUsTN2Qk6yThmfMk= -cosmossdk.io/schema v0.2.0/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= +cosmossdk.io/core v1.0.0-alpha.4 h1:9iuroT9ejDYETCsGkzkvs/wAY/5UFl7nCIINFRxyMJY= +cosmossdk.io/core v1.0.0-alpha.4/go.mod h1:3u9cWq1FAVtiiCrDPpo4LhR+9V6k/ycSG4/Y/tREWCY= +cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29 h1:NxxUo0GMJUbIuVg0R70e3cbn9eFTEuMr7ev1AFvypdY= +cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29/go.mod h1:8s2tPeJtSiQuoyPmr2Ag7meikonISO4Fv4MoO8+ORrs= +cosmossdk.io/schema v0.3.0 h1:01lcaM4trhzZ1HQTfTV8z6Ma1GziOZ/YmdzBN3F720c= +cosmossdk.io/schema v0.3.0/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= diff --git a/collections/indexing.go b/collections/indexing.go index 9d83630bbd4f..5939aed5fea3 100644 --- a/collections/indexing.go +++ b/collections/indexing.go @@ -67,7 +67,7 @@ type moduleDecoder struct { collectionLookup *btree.Map[string, *collectionSchemaCodec] } -func (m moduleDecoder) decodeKV(update schema.KVPairUpdate) ([]schema.ObjectUpdate, error) { +func (m moduleDecoder) decodeKV(update schema.KVPairUpdate) ([]schema.StateObjectUpdate, error) { key := update.Key ks := string(key) var cd *collectionSchemaCodec @@ -87,32 +87,32 @@ func (m moduleDecoder) decodeKV(update schema.KVPairUpdate) ([]schema.ObjectUpda return cd.decodeKVPair(update) } -func (c collectionSchemaCodec) decodeKVPair(update schema.KVPairUpdate) ([]schema.ObjectUpdate, error) { +func (c collectionSchemaCodec) decodeKVPair(update schema.KVPairUpdate) ([]schema.StateObjectUpdate, error) { // strip prefix key := update.Key key = key[len(c.coll.GetPrefix()):] k, err := c.keyDecoder(key) if err != nil { - return []schema.ObjectUpdate{ + return []schema.StateObjectUpdate{ {TypeName: c.coll.GetName()}, }, err } if update.Remove { - return []schema.ObjectUpdate{ + return []schema.StateObjectUpdate{ {TypeName: c.coll.GetName(), Key: k, Delete: true}, }, nil } v, err := c.valueDecoder(update.Value) if err != nil { - return []schema.ObjectUpdate{ + return []schema.StateObjectUpdate{ {TypeName: c.coll.GetName(), Key: k}, }, err } - return []schema.ObjectUpdate{ + return []schema.StateObjectUpdate{ {TypeName: c.coll.GetName(), Key: k, Value: v}, }, nil } diff --git a/collections/naming_test.go b/collections/naming_test.go new file mode 100644 index 000000000000..39b275d920a9 --- /dev/null +++ b/collections/naming_test.go @@ -0,0 +1,59 @@ +package collections + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "cosmossdk.io/collections/codec" +) + +func TestNaming(t *testing.T) { + expectKeyCodecName(t, "u16", Uint16Key.WithName("u16")) + expectKeyCodecName(t, "u32", Uint32Key.WithName("u32")) + expectKeyCodecName(t, "u64", Uint64Key.WithName("u64")) + expectKeyCodecName(t, "i32", Int32Key.WithName("i32")) + expectKeyCodecName(t, "i64", Int64Key.WithName("i64")) + expectKeyCodecName(t, "str", StringKey.WithName("str")) + expectKeyCodecName(t, "bytes", BytesKey.WithName("bytes")) + expectKeyCodecName(t, "bool", BoolKey.WithName("bool")) + + expectValueCodecName(t, "vu16", Uint16Value.WithName("vu16")) + expectValueCodecName(t, "vu32", Uint32Value.WithName("vu32")) + expectValueCodecName(t, "vu64", Uint64Value.WithName("vu64")) + expectValueCodecName(t, "vi32", Int32Value.WithName("vi32")) + expectValueCodecName(t, "vi64", Int64Value.WithName("vi64")) + expectValueCodecName(t, "vstr", StringValue.WithName("vstr")) + expectValueCodecName(t, "vbytes", BytesValue.WithName("vbytes")) + expectValueCodecName(t, "vbool", BoolValue.WithName("vbool")) + + expectKeyCodecNames(t, NamedPairKeyCodec[bool, string]("abc", BoolKey, "def", StringKey), "abc", "def") + expectKeyCodecNames(t, NamedTripleKeyCodec[bool, string, int32]("abc", BoolKey, "def", StringKey, "ghi", Int32Key), "abc", "def", "ghi") + expectKeyCodecNames(t, NamedQuadKeyCodec[bool, string, int32, uint64]("abc", BoolKey, "def", StringKey, "ghi", Int32Key, "jkl", Uint64Key), "abc", "def", "ghi", "jkl") +} + +func expectKeyCodecName[T any](t *testing.T, name string, cdc codec.KeyCodec[T]) { + t.Helper() + schema, err := codec.KeySchemaCodec(cdc) + require.NoError(t, err) + require.Equal(t, 1, len(schema.Fields)) + require.Equal(t, name, schema.Fields[0].Name) +} + +func expectValueCodecName[T any](t *testing.T, name string, cdc codec.ValueCodec[T]) { + t.Helper() + schema, err := codec.ValueSchemaCodec(cdc) + require.NoError(t, err) + require.Equal(t, 1, len(schema.Fields)) + require.Equal(t, name, schema.Fields[0].Name) +} + +func expectKeyCodecNames[T any](t *testing.T, cdc codec.KeyCodec[T], names ...string) { + t.Helper() + schema, err := codec.KeySchemaCodec(cdc) + require.NoError(t, err) + require.Equal(t, len(names), len(schema.Fields)) + for i, name := range names { + require.Equal(t, name, schema.Fields[i].Name) + } +} diff --git a/collections/pair.go b/collections/pair.go index f12aaac1b576..97b678a8c154 100644 --- a/collections/pair.go +++ b/collections/pair.go @@ -6,6 +6,7 @@ import ( "strings" "cosmossdk.io/collections/codec" + "cosmossdk.io/schema" ) // Pair defines a key composed of two keys. @@ -54,9 +55,22 @@ func PairKeyCodec[K1, K2 any](keyCodec1 codec.KeyCodec[K1], keyCodec2 codec.KeyC } } +// NamedPairKeyCodec instantiates a new KeyCodec instance that can encode the Pair, given the KeyCodec of the +// first part of the key and the KeyCodec of the second part of the key. +// It also provides names for the keys which are used for indexing purposes. +func NamedPairKeyCodec[K1, K2 any](key1Name string, keyCodec1 codec.KeyCodec[K1], key2Name string, keyCodec2 codec.KeyCodec[K2]) codec.KeyCodec[Pair[K1, K2]] { + return pairKeyCodec[K1, K2]{ + key1Name: key1Name, + key2Name: key2Name, + keyCodec1: keyCodec1, + keyCodec2: keyCodec2, + } +} + type pairKeyCodec[K1, K2 any] struct { - keyCodec1 codec.KeyCodec[K1] - keyCodec2 codec.KeyCodec[K2] + key1Name, key2Name string + keyCodec1 codec.KeyCodec[K1] + keyCodec2 codec.KeyCodec[K2] } func (p pairKeyCodec[K1, K2]) KeyCodec1() codec.KeyCodec[K1] { return p.keyCodec1 } @@ -216,6 +230,39 @@ func (p pairKeyCodec[K1, K2]) DecodeJSON(b []byte) (Pair[K1, K2], error) { return Join(k1, k2), nil } +func (p pairKeyCodec[K1, K2]) Name() string { + return fmt.Sprintf("%s,%s", p.key1Name, p.key2Name) +} + +func (p pairKeyCodec[K1, K2]) SchemaCodec() (codec.SchemaCodec[Pair[K1, K2]], error) { + field1, err := getNamedKeyField(p.keyCodec1, p.key1Name) + if err != nil { + return codec.SchemaCodec[Pair[K1, K2]]{}, fmt.Errorf("error getting key1 field: %w", err) + } + + field2, err := getNamedKeyField(p.keyCodec2, p.key2Name) + if err != nil { + return codec.SchemaCodec[Pair[K1, K2]]{}, fmt.Errorf("error getting key2 field: %w", err) + } + + return codec.SchemaCodec[Pair[K1, K2]]{ + Fields: []schema.Field{field1, field2}, + }, nil +} + +func getNamedKeyField[T any](keyCdc codec.KeyCodec[T], name string) (schema.Field, error) { + keySchema, err := codec.KeySchemaCodec(keyCdc) + if err != nil { + return schema.Field{}, err + } + if len(keySchema.Fields) != 1 { + return schema.Field{}, fmt.Errorf("key schema in composite key has more than one field, got %v", keySchema.Fields) + } + field := keySchema.Fields[0] + field.Name = name + return field, nil +} + // NewPrefixUntilPairRange defines a collection query which ranges until the provided Pair prefix. // Unstable: this API might change in the future. func NewPrefixUntilPairRange[K1, K2 any](prefix K1) *PairRange[K1, K2] { diff --git a/collections/quad.go b/collections/quad.go index bd2844728360..a5dfc2929b01 100644 --- a/collections/quad.go +++ b/collections/quad.go @@ -6,6 +6,7 @@ import ( "strings" "cosmossdk.io/collections/codec" + "cosmossdk.io/schema" ) // Quad defines a multipart key composed of four keys. @@ -79,11 +80,28 @@ func QuadKeyCodec[K1, K2, K3, K4 any](keyCodec1 codec.KeyCodec[K1], keyCodec2 co } } +// NamedQuadKeyCodec instantiates a new KeyCodec instance that can encode the Quad, given +// the KeyCodecs of the four parts of the key, in order. +// The provided names are used to identify the parts of the key in the schema for indexing. +func NamedQuadKeyCodec[K1, K2, K3, K4 any](key1Name string, keyCodec1 codec.KeyCodec[K1], key2Name string, keyCodec2 codec.KeyCodec[K2], key3Name string, keyCodec3 codec.KeyCodec[K3], key4Name string, keyCodec4 codec.KeyCodec[K4]) codec.KeyCodec[Quad[K1, K2, K3, K4]] { + return quadKeyCodec[K1, K2, K3, K4]{ + name1: key1Name, + keyCodec1: keyCodec1, + name2: key2Name, + keyCodec2: keyCodec2, + name3: key3Name, + keyCodec3: keyCodec3, + name4: key4Name, + keyCodec4: keyCodec4, + } +} + type quadKeyCodec[K1, K2, K3, K4 any] struct { - keyCodec1 codec.KeyCodec[K1] - keyCodec2 codec.KeyCodec[K2] - keyCodec3 codec.KeyCodec[K3] - keyCodec4 codec.KeyCodec[K4] + name1, name2, name3, name4 string + keyCodec1 codec.KeyCodec[K1] + keyCodec2 codec.KeyCodec[K2] + keyCodec3 codec.KeyCodec[K3] + keyCodec4 codec.KeyCodec[K4] } type jsonQuadKey [4]json.RawMessage @@ -338,6 +356,32 @@ func (t quadKeyCodec[K1, K2, K3, K4]) SizeNonTerminal(key Quad[K1, K2, K3, K4]) return size } +func (t quadKeyCodec[K1, K2, K3, K4]) SchemaCodec() (codec.SchemaCodec[Quad[K1, K2, K3, K4]], error) { + field1, err := getNamedKeyField(t.keyCodec1, t.name1) + if err != nil { + return codec.SchemaCodec[Quad[K1, K2, K3, K4]]{}, fmt.Errorf("error getting key1 field: %w", err) + } + + field2, err := getNamedKeyField(t.keyCodec2, t.name2) + if err != nil { + return codec.SchemaCodec[Quad[K1, K2, K3, K4]]{}, fmt.Errorf("error getting key2 field: %w", err) + } + + field3, err := getNamedKeyField(t.keyCodec3, t.name3) + if err != nil { + return codec.SchemaCodec[Quad[K1, K2, K3, K4]]{}, fmt.Errorf("error getting key3 field: %w", err) + } + + field4, err := getNamedKeyField(t.keyCodec4, t.name4) + if err != nil { + return codec.SchemaCodec[Quad[K1, K2, K3, K4]]{}, fmt.Errorf("error getting key4 field: %w", err) + } + + return codec.SchemaCodec[Quad[K1, K2, K3, K4]]{ + Fields: []schema.Field{field1, field2, field3, field4}, + }, nil +} + // NewPrefixUntilQuadRange defines a collection query which ranges until the provided Quad prefix. // Unstable: this API might change in the future. func NewPrefixUntilQuadRange[K1, K2, K3, K4 any](k1 K1) Ranger[Quad[K1, K2, K3, K4]] { diff --git a/collections/triple.go b/collections/triple.go index 9733d9984099..e4a07970945c 100644 --- a/collections/triple.go +++ b/collections/triple.go @@ -6,6 +6,7 @@ import ( "strings" "cosmossdk.io/collections/codec" + "cosmossdk.io/schema" ) // Triple defines a multipart key composed of three keys. @@ -64,10 +65,22 @@ func TripleKeyCodec[K1, K2, K3 any](keyCodec1 codec.KeyCodec[K1], keyCodec2 code } } +func NamedTripleKeyCodec[K1, K2, K3 any](key1Name string, keyCodec1 codec.KeyCodec[K1], key2Name string, keyCodec2 codec.KeyCodec[K2], key3Name string, keyCodec3 codec.KeyCodec[K3]) codec.KeyCodec[Triple[K1, K2, K3]] { + return tripleKeyCodec[K1, K2, K3]{ + key1Name: key1Name, + key2Name: key2Name, + key3Name: key3Name, + keyCodec1: keyCodec1, + keyCodec2: keyCodec2, + keyCodec3: keyCodec3, + } +} + type tripleKeyCodec[K1, K2, K3 any] struct { - keyCodec1 codec.KeyCodec[K1] - keyCodec2 codec.KeyCodec[K2] - keyCodec3 codec.KeyCodec[K3] + key1Name, key2Name, key3Name string + keyCodec1 codec.KeyCodec[K1] + keyCodec2 codec.KeyCodec[K2] + keyCodec3 codec.KeyCodec[K3] } type jsonTripleKey [3]json.RawMessage @@ -273,6 +286,31 @@ func (t tripleKeyCodec[K1, K2, K3]) SizeNonTerminal(key Triple[K1, K2, K3]) int return size } +func (t tripleKeyCodec[K1, K2, K3]) Name() string { + return fmt.Sprintf("%s,%s,%s", t.key1Name, t.key2Name, t.key3Name) +} + +func (t tripleKeyCodec[K1, K2, K3]) SchemaCodec() (codec.SchemaCodec[Triple[K1, K2, K3]], error) { + field1, err := getNamedKeyField(t.keyCodec1, t.key1Name) + if err != nil { + return codec.SchemaCodec[Triple[K1, K2, K3]]{}, fmt.Errorf("error getting key1 field: %w", err) + } + + field2, err := getNamedKeyField(t.keyCodec2, t.key2Name) + if err != nil { + return codec.SchemaCodec[Triple[K1, K2, K3]]{}, fmt.Errorf("error getting key2 field: %w", err) + } + + field3, err := getNamedKeyField(t.keyCodec3, t.key3Name) + if err != nil { + return codec.SchemaCodec[Triple[K1, K2, K3]]{}, fmt.Errorf("error getting key3 field: %w", err) + } + + return codec.SchemaCodec[Triple[K1, K2, K3]]{ + Fields: []schema.Field{field1, field2, field3}, + }, nil +} + // NewPrefixUntilTripleRange defines a collection query which ranges until the provided Pair prefix. // Unstable: this API might change in the future. func NewPrefixUntilTripleRange[K1, K2, K3 any](k1 K1) Ranger[Triple[K1, K2, K3]] { diff --git a/core/CHANGELOG.md b/core/CHANGELOG.md index 60cabab88dd1..c234cc971948 100644 --- a/core/CHANGELOG.md +++ b/core/CHANGELOG.md @@ -36,7 +36,12 @@ Ref: https://keepachangelog.com/en/1.0.0/ ## [Unreleased] - +## [v1.0.0-alpha.3](https://github.com/cosmos/cosmos-sdk/releases/tag/core%2Fv1.0.0-alpha.3) + +### Features + +* [#21719](https://github.com/cosmos/cosmos-sdk/pull/21719) Make `core/event` as a type alias of `schema/appdata`. + ## [v1.0.0-alpha.2](https://github.com/cosmos/cosmos-sdk/releases/tag/core%2Fv1.0.0-alpha.2) ### Features diff --git a/core/README.md b/core/README.md index 6ab95a67a6f1..f54197bd7be5 100644 --- a/core/README.md +++ b/core/README.md @@ -10,7 +10,7 @@ Key features and principles: 4. Modules depend solely on core APIs for maximum compatibility. 5. New API additions undergo thorough consideration to maintain stability. 6. Adheres to a no-breaking-changes policy for reliable dependency management. -7. Aimed to have zero dependencies, ensuring a lightweight and self-contained foundation. +7. Aimed to only depend on `schema`, ensuring a lightweight and self-contained foundation. The core module offers the [appmodule](https://pkg.go.dev/cosmossdk.io/core/appmodule) and [appmodule/v2](https://pkg.go.dev/cosmossdk.io/core/appmodule/v2) packages that include APIs to describe how modules can be written. Additionally, it contains all core services APIs that can be used in modules to interact with the SDK, majoritarily via the `appmodule.Environment` struct. diff --git a/core/appmodule/v2/handlers.go b/core/appmodule/v2/handlers.go index b42698b7e86f..aa11ff58a70c 100644 --- a/core/appmodule/v2/handlers.go +++ b/core/appmodule/v2/handlers.go @@ -10,8 +10,8 @@ import ( type ( // PreMsgHandler is a handler that is executed before Handler. If it errors the execution reverts. PreMsgHandler = func(ctx context.Context, msg transaction.Msg) error - // Handler handles the state transition of the provided message. - Handler = func(ctx context.Context, msg transaction.Msg) (msgResp transaction.Msg, err error) + // HandlerFunc handles the state transition of the provided message. + HandlerFunc = func(ctx context.Context, msg transaction.Msg) (msgResp transaction.Msg, err error) // PostMsgHandler runs after Handler, only if Handler does not error. If PostMsgHandler errors // then the execution is reverted. PostMsgHandler = func(ctx context.Context, msg, msgResp transaction.Msg) error @@ -19,10 +19,10 @@ type ( // PreMsgRouter is a router that allows you to register PreMsgHandlers for specific message types. type PreMsgRouter interface { - // RegisterPreHandler will register a specific message handler hooking into the message with + // RegisterPreMsgHandler will register a specific message handler hooking into the message with // the provided name. RegisterPreMsgHandler(msgName string, handler PreMsgHandler) - // RegisterGlobalPreHandler will register a global message handler hooking into any message + // RegisterGlobalPreMsgHandler will register a global message handler hooking into any message // being executed. RegisterGlobalPreMsgHandler(handler PreMsgHandler) } @@ -64,10 +64,10 @@ func RegisterMsgPreHandler[Req transaction.Msg]( // PostMsgRouter is a router that allows you to register PostMsgHandlers for specific message types. type PostMsgRouter interface { - // RegisterPostHandler will register a specific message handler hooking after the execution of message with + // RegisterPostMsgHandler will register a specific message handler hooking after the execution of message with // the provided name. RegisterPostMsgHandler(msgName string, handler PostMsgHandler) - // RegisterGlobalPostHandler will register a global message handler hooking after the execution of any message. + // RegisterGlobalPostMsgHandler will register a global message handler hooking after the execution of any message. RegisterGlobalPostMsgHandler(handler PostMsgHandler) } @@ -76,7 +76,7 @@ type HasPostMsgHandlers interface { RegisterPostMsgHandlers(router PostMsgRouter) } -// RegisterPostHandler is a helper function that modules can use to not lose type safety when registering handlers to the +// RegisterPostMsgHandler is a helper function that modules can use to not lose type safety when registering handlers to the // PostMsgRouter. Example usage: // ```go // @@ -110,9 +110,20 @@ func RegisterPostMsgHandler[Req, Resp transaction.Msg]( router.RegisterPostMsgHandler(msgName, untypedHandler) } +// Handler defines a handler descriptor. +type Handler struct { + // Func defines the actual handler, the function that runs a request and returns a response. + // Can be query handler or msg handler. + Func HandlerFunc + // MakeMsg instantiates the type of the request, can be used in decoding contexts. + MakeMsg func() transaction.Msg + // MakeMsgResp instantiates a new response, can be used in decoding contexts. + MakeMsgResp func() transaction.Msg +} + // MsgRouter is a router that allows you to register Handlers for specific message types. type MsgRouter = interface { - RegisterHandler(msgName string, handler Handler) error + RegisterHandler(handler Handler) } // HasMsgHandlers is an interface that modules must implement if they want to register Handlers. @@ -142,27 +153,34 @@ type HasQueryHandlers interface { // // func (m Module) RegisterMsgHandlers(router appmodule.MsgRouter) { // handlers := keeper.NewHandlers(m.keeper) -// err := appmodule.RegisterHandler(router, gogoproto.MessageName(types.MsgMint{}), handlers.MsgMint) +// err := appmodule.RegisterHandler(router, handlers.MsgMint) // } // // func (m Module) RegisterQueryHandlers(router appmodule.QueryRouter) { // handlers := keeper.NewHandlers(m.keeper) -// err := appmodule.RegisterHandler(router, gogoproto.MessageName(types.QueryBalanceRequest{}), handlers.QueryBalance) +// err := appmodule.RegisterHandler(router, handlers.QueryBalance) // } // // ``` -func RegisterHandler[Req, Resp transaction.Msg]( +func RegisterMsgHandler[Req, Resp any, PReq transaction.GenericMsg[Req], PResp transaction.GenericMsg[Resp]]( router MsgRouter, - msgName string, - handler func(ctx context.Context, msg Req) (msgResp Resp, err error), -) error { + handler func(ctx context.Context, msg PReq) (msgResp PResp, err error), +) { untypedHandler := func(ctx context.Context, m transaction.Msg) (transaction.Msg, error) { - typed, ok := m.(Req) + typed, ok := m.(PReq) if !ok { return nil, fmt.Errorf("unexpected type %T, wanted: %T", m, *new(Req)) } return handler(ctx, typed) } - return router.RegisterHandler(msgName, untypedHandler) + router.RegisterHandler(Handler{ + Func: untypedHandler, + MakeMsg: func() transaction.Msg { + return PReq(new(Req)) + }, + MakeMsgResp: func() transaction.Msg { + return PResp(new(Resp)) + }, + }) } diff --git a/core/event/event.go b/core/event/event.go index 4304e6e2b4af..de8fe739b379 100644 --- a/core/event/event.go +++ b/core/event/event.go @@ -1,29 +1,24 @@ package event +import "cosmossdk.io/schema/appdata" + // Attribute is a kv-pair event attribute. -type Attribute struct { - Key, Value string -} +type Attribute = appdata.EventAttribute func NewAttribute(key, value string) Attribute { return Attribute{Key: key, Value: value} } // Events represents a list of events. -type Events struct { - Events []Event -} +type Events = appdata.EventData func NewEvents(events ...Event) Events { return Events{Events: events} } // Event defines how an event will emitted -type Event struct { - Type string - Attributes []Attribute -} +type Event = appdata.Event func NewEvent(ty string, attrs ...Attribute) Event { - return Event{Type: ty, Attributes: attrs} + return Event{Type: ty, Attributes: func() ([]Attribute, error) { return attrs, nil }} } diff --git a/core/go.mod b/core/go.mod index 8f691cc75063..61b97a200010 100644 --- a/core/go.mod +++ b/core/go.mod @@ -1,9 +1,11 @@ module cosmossdk.io/core -// Core is meant to have zero dependencies, so we can use it as a dependency +// Core is meant to have only a dependency on cosmossdk.io/schema, so we can use it as a dependency // in other modules without having to worry about circular dependencies. go 1.23 +require cosmossdk.io/schema v0.3.0 + // Version tagged too early and incompatible with v0.50 (latest at the time of tagging) retract v0.12.0 diff --git a/core/go.sum b/core/go.sum index e69de29bb2d1..18e538dae2df 100644 --- a/core/go.sum +++ b/core/go.sum @@ -0,0 +1,2 @@ +cosmossdk.io/schema v0.3.0 h1:01lcaM4trhzZ1HQTfTV8z6Ma1GziOZ/YmdzBN3F720c= +cosmossdk.io/schema v0.3.0/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= diff --git a/core/header/service.go b/core/header/service.go index 15e6d4257425..8d36087a059c 100644 --- a/core/header/service.go +++ b/core/header/service.go @@ -35,7 +35,7 @@ func (i *Info) Bytes() ([]byte, error) { // Encode Hash if len(i.Hash) != hashSize { - return nil, errors.New("invalid hash size") + return nil, errors.New("invalid Hash size") } buf = append(buf, i.Hash...) @@ -47,7 +47,7 @@ func (i *Info) Bytes() ([]byte, error) { // Encode AppHash if len(i.AppHash) != hashSize { - return nil, errors.New("invalid hash size") + return nil, errors.New("invalid AppHash size") } buf = append(buf, i.AppHash...) diff --git a/core/server/app.go b/core/server/app.go index 9576fa8825f8..56a0c0862777 100644 --- a/core/server/app.go +++ b/core/server/app.go @@ -39,10 +39,6 @@ type TxResult struct { Resp []transaction.Msg // Error produced by the transaction. Error error - // Code produced by the transaction. - // A non-zero code is an error that is either define by the module via the cosmossdk.io/errors/v2 package - // or injected through the antehandler along the execution of the transaction. - Code uint32 // GasWanted is the maximum units of work we allow this tx to perform. GasWanted uint64 // GasUsed is the amount of gas actually consumed. diff --git a/core/store/service.go b/core/store/service.go index 11eeaf0de9b3..6faec8bdb0ce 100644 --- a/core/store/service.go +++ b/core/store/service.go @@ -10,6 +10,11 @@ type KVStoreService interface { OpenKVStore(context.Context) KVStore } +// KVStoreServiceFactory is a function that creates a new KVStoreService. +// It can be used to override the default KVStoreService bindings for cases +// where an application must supply a custom stateful backend. +type KVStoreServiceFactory func([]byte) KVStoreService + // MemoryStoreService represents a unique, non-forgeable handle to a memory-backed // KVStore. It should be provided as a module-scoped dependency by the runtime // module being used to build the app. diff --git a/core/testing/go.mod b/core/testing/go.mod index ac670ca1d068..95f3b6a38c59 100644 --- a/core/testing/go.mod +++ b/core/testing/go.mod @@ -3,7 +3,9 @@ module cosmossdk.io/core/testing go 1.23 require ( - cosmossdk.io/core v1.0.0-alpha.2 + cosmossdk.io/core v1.0.0-alpha.4 github.com/golang/mock v1.6.0 github.com/tidwall/btree v1.7.0 ) + +require cosmossdk.io/schema v0.3.0 // indirect diff --git a/core/testing/go.sum b/core/testing/go.sum index 056899b14a3b..9fc6d98fad48 100644 --- a/core/testing/go.sum +++ b/core/testing/go.sum @@ -1,5 +1,7 @@ -cosmossdk.io/core v1.0.0-alpha.2 h1:epU0Xwces4Rgl5bMhHHkXGaGDcyucNGlC/JDH+Suckg= -cosmossdk.io/core v1.0.0-alpha.2/go.mod h1:abgLjeFLhtuKIYZWSPlVUgQBrKObO7ULV35KYfexE90= +cosmossdk.io/core v1.0.0-alpha.4 h1:9iuroT9ejDYETCsGkzkvs/wAY/5UFl7nCIINFRxyMJY= +cosmossdk.io/core v1.0.0-alpha.4/go.mod h1:3u9cWq1FAVtiiCrDPpo4LhR+9V6k/ycSG4/Y/tREWCY= +cosmossdk.io/schema v0.3.0 h1:01lcaM4trhzZ1HQTfTV8z6Ma1GziOZ/YmdzBN3F720c= +cosmossdk.io/schema v0.3.0/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= github.com/tidwall/btree v1.7.0 h1:L1fkJH/AuEh5zBnnBbmTwQ5Lt+bRJ5A8EWecslvo9iI= diff --git a/core/transaction/transaction.go b/core/transaction/transaction.go index 5211c54c66e2..3efd88b5aa29 100644 --- a/core/transaction/transaction.go +++ b/core/transaction/transaction.go @@ -10,6 +10,14 @@ type ( Identity = []byte ) +// GenericMsg defines a generic version of a Msg. +// The GenericMsg refers to the non pointer version of Msg, +// and is required to allow its instantiations in generic contexts. +type GenericMsg[T any] interface { + *T + Msg +} + // Codec defines the TX codec, which converts a TX from bytes to its concrete representation. type Codec[T Tx] interface { // Decode decodes the tx bytes into a DecodedTx, containing diff --git a/crypto/README.md b/crypto/README.md new file mode 100644 index 000000000000..269d840c6e80 --- /dev/null +++ b/crypto/README.md @@ -0,0 +1,53 @@ +# Crypto + +The `crypto` directory contains the components responsible for handling cryptographic operations, key management, and secure interactions with hardware wallets. + +## Components + +### Keyring + +Keyring is the primary interface for managing cryptographic keys. It provides a unified API to create, store, retrieve, and manage keys securely across different storage backends. + +#### Supported Backends + +* **OS**: Uses the operating system's default credential store. +* **File**: Stores encrypted keyring in the application's configuration directory. +* **KWallet**: Integrates with KDE Wallet Manager. +* **Pass**: Leverages the `pass` command-line utility. +* **Keyctl**: Uses Linux's kernel security key management system. +* **Test**: Stores (insecurely) keys to disk for testing purposes. +* **Memory**: Provides transient storage where keys are discarded when the process terminates. + +### Codec + +The Codec component handles serialization and deserialization of cryptographic structures in the crypto package. It ensures proper encoding of keys, signatures, and other artifacts for storage and transmission. The Codec also manages conversion between CometBFT and SDK key formats. + +### Ledger Integration + +Support for Ledger hardware wallets is integrated to provide enhanced security for key management and signing operations. The Ledger integration supports SECP256K1 keys and offers various features: + +#### Key Features + +* **Public Key Retrieval**: Supports both safe (with user verification) and unsafe (without user verification) methods to retrieve public keys from the Ledger device. +* **Address Generation**: Can generate and display Bech32 addresses on the Ledger device for user verification. +* **Transaction Signing**: Allows signing of transactions with user confirmation on the Ledger device. +* **Multiple HD Path Support**: Supports various BIP44 derivation paths for key generation and management. +* **Customizable Options**: Provides options to customize Ledger usage, including app name, public key creation, and DER to BER signature conversion. + +#### Implementation Details + +* The integration is built to work with or without CGO. +* It includes a mock implementation for testing purposes, which can be enabled with the `test_ledger_mock` build tag. +* The real Ledger device interaction is implemented when the `ledger` build tag is used. +* The integration supports both SIGN_MODE_LEGACY_AMINO_JSON and SIGN_MODE_TEXTUAL signing modes. + +#### Usage Considerations + +* Ledger support requires the appropriate Cosmos app to be installed and opened on the Ledger device. +* The integration includes safeguards to prevent key overwriting and ensures that the correct device and app are being used. + +#### Security Notes + +* The integration includes methods to validate keys and addresses with user confirmation on the Ledger device. +* It's recommended to use the safe methods that require user verification for critical operations like key generation and address display. +* The mock implementation should only be used for testing and development purposes, not in production environments. \ No newline at end of file diff --git a/crypto/hd/hdpath_test.go b/crypto/hd/hdpath_test.go index cce81df86f20..fa203911a58c 100644 --- a/crypto/hd/hdpath_test.go +++ b/crypto/hd/hdpath_test.go @@ -107,9 +107,7 @@ func TestCreateHDPath(t *testing.T) { {"m/44'/114'/1'/1/0", args{114, 1, 1}, hd.BIP44Params{Purpose: 44, CoinType: 114, Account: 1, AddressIndex: 1}}, } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { - tt := tt require.Equal(t, tt.want, *hd.CreateHDPath(tt.args.coinType, tt.args.account, tt.args.index)) }) } @@ -170,7 +168,6 @@ func TestDeriveHDPathRange(t *testing.T) { } for _, tt := range tests { - tt := tt t.Run(tt.path, func(t *testing.T) { master, ch := hd.ComputeMastersFromSeed(seed) _, err := hd.DerivePrivateKeyForPath(master, ch, tt.path) @@ -297,7 +294,6 @@ func TestDerivePrivateKeyForPathDoNotCrash(t *testing.T) { } for _, path := range paths { - path := path t.Run(path, func(t *testing.T) { _, _ = hd.DerivePrivateKeyForPath([32]byte{}, [32]byte{}, path) }) diff --git a/crypto/keyring/autocli.go b/crypto/keyring/autocli.go index 0dd91ff60a43..26f39b3e4362 100644 --- a/crypto/keyring/autocli.go +++ b/crypto/keyring/autocli.go @@ -2,6 +2,7 @@ package keyring import ( signingv1beta1 "cosmossdk.io/api/cosmos/tx/signing/v1beta1" + "cosmossdk.io/core/address" cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing" @@ -21,15 +22,22 @@ type autoCLIKeyring interface { // Sign signs the given bytes with the key with the given name. Sign(name string, msg []byte, signMode signingv1beta1.SignMode) ([]byte, error) + + // KeyType returns the type of the key. + KeyType(name string) (uint, error) + + // KeyInfo given a key name or address returns key name, key address and key type. + KeyInfo(name string) (string, string, uint, error) } // NewAutoCLIKeyring wraps the SDK keyring and make it compatible with the AutoCLI keyring interfaces. -func NewAutoCLIKeyring(kr Keyring) (autoCLIKeyring, error) { - return &autoCLIKeyringAdapter{kr}, nil +func NewAutoCLIKeyring(kr Keyring, ac address.Codec) (autoCLIKeyring, error) { + return &autoCLIKeyringAdapter{kr, ac}, nil } type autoCLIKeyringAdapter struct { Keyring + ac address.Codec } func (a *autoCLIKeyringAdapter) List() ([]string, error) { @@ -84,3 +92,40 @@ func (a *autoCLIKeyringAdapter) Sign(name string, msg []byte, signMode signingv1 signBytes, _, err := a.Keyring.Sign(record.Name, msg, sdkSignMode) return signBytes, err } + +func (a *autoCLIKeyringAdapter) KeyType(name string) (uint, error) { + record, err := a.Keyring.Key(name) + if err != nil { + return 0, err + } + + return uint(record.GetType()), nil +} + +func (a *autoCLIKeyringAdapter) KeyInfo(nameOrAddr string) (string, string, uint, error) { + addr, err := a.ac.StringToBytes(nameOrAddr) + if err != nil { + // If conversion fails, it's likely a name, not an address + record, err := a.Keyring.Key(nameOrAddr) + if err != nil { + return "", "", 0, err + } + addr, err = record.GetAddress() + if err != nil { + return "", "", 0, err + } + addrStr, err := a.ac.BytesToString(addr) + if err != nil { + return "", "", 0, err + } + return record.Name, addrStr, uint(record.GetType()), nil + } + + // If conversion succeeds, it's an address, get the key info by address + record, err := a.Keyring.KeyByAddress(addr) + if err != nil { + return "", "", 0, err + } + + return record.Name, nameOrAddr, uint(record.GetType()), nil +} diff --git a/crypto/keyring/keyring_test.go b/crypto/keyring/keyring_test.go index 519cd01142f8..850cbcbafe04 100644 --- a/crypto/keyring/keyring_test.go +++ b/crypto/keyring/keyring_test.go @@ -2003,7 +2003,7 @@ func TestRenameKey(t *testing.T) { } for _, tc := range testCases { - tc := tc + kr := newKeyring(t, "testKeyring") t.Run(tc.name, func(t *testing.T) { tc.run(kr) diff --git a/crypto/keyring/signing_algorithms_test.go b/crypto/keyring/signing_algorithms_test.go index 624e491d098a..1ac7d9cc352e 100644 --- a/crypto/keyring/signing_algorithms_test.go +++ b/crypto/keyring/signing_algorithms_test.go @@ -36,7 +36,6 @@ func TestNewSigningAlgoByString(t *testing.T) { list := SigningAlgoList{hd.Secp256k1} for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { algorithm, err := NewSigningAlgoFromString(tt.algoStr, list) if tt.isSupported { diff --git a/crypto/keys/secp256k1/secp256k1.go b/crypto/keys/secp256k1/secp256k1.go index 4073684076ff..927b0eafe9e1 100644 --- a/crypto/keys/secp256k1/secp256k1.go +++ b/crypto/keys/secp256k1/secp256k1.go @@ -12,7 +12,7 @@ import ( "github.com/cometbft/cometbft/crypto" secp256k1dcrd "github.com/decred/dcrd/dcrec/secp256k1/v4" "gitlab.com/yawning/secp256k1-voi/secec" - "golang.org/x/crypto/ripemd160" //nolint: staticcheck // keep around for backwards compatibility + "golang.org/x/crypto/ripemd160" //nolint:staticcheck,gosec // keep around for backwards compatibility errorsmod "cosmossdk.io/errors" @@ -173,8 +173,8 @@ func (pubKey *PubKey) Address() crypto.Address { } sha := sha256.Sum256(pubKey.Key) - hasherRIPEMD160 := ripemd160.New() - hasherRIPEMD160.Write(sha[:]) // does not error + hasherRIPEMD160 := ripemd160.New() //nolint:gosec // keep around for backwards compatibility + hasherRIPEMD160.Write(sha[:]) // does not error return crypto.Address(hasherRIPEMD160.Sum(nil)) } diff --git a/crypto/keys/secp256k1/secp256k1_internal_test.go b/crypto/keys/secp256k1/secp256k1_internal_test.go index 08afa6014e4b..c0df3ed5286b 100644 --- a/crypto/keys/secp256k1/secp256k1_internal_test.go +++ b/crypto/keys/secp256k1/secp256k1_internal_test.go @@ -27,7 +27,6 @@ func Test_genPrivKey(t *testing.T) { {"valid because 0 < 1 < N", validOne, false}, } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { if tt.shouldPanic { require.Panics(t, func() { diff --git a/crypto/keys/secp256k1/secp256k1_test.go b/crypto/keys/secp256k1/secp256k1_test.go index 76db9ec72306..bafab8b9f3af 100644 --- a/crypto/keys/secp256k1/secp256k1_test.go +++ b/crypto/keys/secp256k1/secp256k1_test.go @@ -255,7 +255,6 @@ func TestGenPrivKeyFromSecret(t *testing.T) { {"another seed used in cosmos tests #3", []byte("")}, } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { gotPrivKey := secp256k1.GenPrivKeyFromSecret(tt.secret) require.NotNil(t, gotPrivKey) diff --git a/crypto/ledger/ledger_secp256k1.go b/crypto/ledger/ledger_secp256k1.go index 67dcc73981ab..3449d0bfd1b1 100644 --- a/crypto/ledger/ledger_secp256k1.go +++ b/crypto/ledger/ledger_secp256k1.go @@ -341,6 +341,12 @@ func getPubKeyUnsafe(device SECP256K1, path hd.BIP44Params) (types.PubKey, error func getPubKeyAddrSafe(device SECP256K1, path hd.BIP44Params, hrp string) (types.PubKey, string, error) { publicKey, addr, err := device.GetAddressPubKeySECP256K1(path.DerivationPath(), hrp) if err != nil { + // Check special case if user is trying to use an index > 100 + if path.AddressIndex > 100 { + return nil, "", fmt.Errorf("%w: cannot derive paths where index > 100: %s "+ + "This is a security measure to avoid very hard to find derivation paths introduced by a possible attacker. "+ + "You can disable this by setting expert mode in your ledger device. Do this at your own risk", err, path) + } return nil, "", fmt.Errorf("%w: address rejected for path %s", err, path) } diff --git a/crypto/types/compact_bit_array_test.go b/crypto/types/compact_bit_array_test.go index 4831e8e681ea..1f7f276cff22 100644 --- a/crypto/types/compact_bit_array_test.go +++ b/crypto/types/compact_bit_array_test.go @@ -58,7 +58,6 @@ func TestBitArrayEqual(t *testing.T) { {name: "different should not be equal", b1: big1, b2: big2, eq: false}, } for _, tc := range cases { - tc := tc t.Run(tc.name, func(t *testing.T) { eq := tc.b1.Equal(tc.b2) require.Equal(t, tc.eq, eq) @@ -102,7 +101,6 @@ func TestJSONMarshalUnmarshal(t *testing.T) { } for _, tc := range testCases { - tc := tc t.Run(tc.bA.String(), func(t *testing.T) { bz, err := json.Marshal(tc.bA) require.NoError(t, err) @@ -162,7 +160,6 @@ func TestCompactMarshalUnmarshal(t *testing.T) { } for _, tc := range testCases { - tc := tc t.Run(tc.bA.String(), func(t *testing.T) { bz := tc.bA.CompactMarshal() @@ -209,8 +206,6 @@ func TestCompactBitArrayNumOfTrueBitsBefore(t *testing.T) { {`"______________xx"`, []int{14, 15}, []int{0, 1}}, } for tcIndex, tc := range testCases { - tc := tc - tcIndex := tcIndex t.Run(tc.marshalledBA, func(t *testing.T) { var bA *CompactBitArray err := json.Unmarshal([]byte(tc.marshalledBA), &bA) @@ -283,7 +278,6 @@ func TestNewCompactBitArrayCrashWithLimits(t *testing.T) { } for _, tt := range tests { - tt := tt t.Run(fmt.Sprintf("%d", tt.in), func(t *testing.T) { got := NewCompactBitArray(tt.in) if g := got != nil; g != tt.mustPass { diff --git a/depinject/go.mod b/depinject/go.mod index 8418efbddc24..12e18e6a5c56 100644 --- a/depinject/go.mod +++ b/depinject/go.mod @@ -7,7 +7,7 @@ require ( github.com/cosmos/gogoproto v1.7.0 github.com/stretchr/testify v1.9.0 golang.org/x/exp v0.0.0-20231006140011-7918f672742d - google.golang.org/grpc v1.66.2 + google.golang.org/grpc v1.67.1 google.golang.org/protobuf v1.34.2 gotest.tools/v3 v3.5.1 sigs.k8s.io/yaml v1.4.0 @@ -23,7 +23,7 @@ require ( golang.org/x/net v0.29.0 // indirect golang.org/x/sys v0.25.0 // indirect golang.org/x/text v0.18.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f // indirect gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/depinject/go.sum b/depinject/go.sum index 743ca78205ce..252c8bd7d025 100644 --- a/depinject/go.sum +++ b/depinject/go.sum @@ -46,8 +46,8 @@ golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:pPJltXNxVzT4pK9yD8vR9X75DaWYYmLGMsEvBfFQZzQ= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f h1:cUMEy+8oS78BWIH9OWazBkzbr090Od9tWBNtZHkOhf0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= google.golang.org/grpc v1.64.1 h1:LKtvyfbX3UGVPFcGqJ9ItpVWW6oN/2XqTxfAnwRRXiA= google.golang.org/grpc v1.64.1/go.mod h1:hiQF4LFZelK2WKaP6W0L92zGHtiQdZxk8CrSdvyjeP0= google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= diff --git a/docs/Introduction.md b/docs/Introduction.md index 80c5a7a0a9c4..5f87480aaced 100644 --- a/docs/Introduction.md +++ b/docs/Introduction.md @@ -21,7 +21,7 @@ Get familiar with the SDK and explore its main concepts. * [**Core Concepts**](learn/advanced/00-baseapp.md) - Read about the core concepts like baseapp, the store, or the server. * [**Building Modules**](build/building-modules/00-intro.md) - Discover how to build modules for the Cosmos SDK. * [**Running a Node**](https://docs.cosmos.network/main/user/run-node/keyring) - Running and interacting with nodes using the CLI and API. -* [**Modules**](./build/modules/README.md) - Explore existing modules to build your application with. +* [**Modules**](./build/building-modules/00-intro.md) - Explore existing modules to build your application with. ## Explore the Stack diff --git a/docs/architecture/PROCESS.md b/docs/architecture/PROCESS.md index bca4cdf51b15..15e11639c409 100644 --- a/docs/architecture/PROCESS.md +++ b/docs/architecture/PROCESS.md @@ -1,8 +1,8 @@ # ADR Creation Process 1. Copy the `adr-template.md` file. Use the following filename pattern: `adr-next_number-title.md` -2. Create a draft Pull Request if you want to get an early feedback. -3. Make sure the context and solution is clear and well documented. +2. Create a draft Pull Request if you want to get early feedback. +3. Make sure the context and solution are clear and well documented. 4. Add an entry to a list in the [README](./README.md) file. 5. Create a Pull Request to propose a new ADR. @@ -14,7 +14,7 @@ An ADR is a document to document an implementation and design that may or may no ADR creation is an **iterative** process. Instead of having a high amount of communication overhead, an ADR is used when there is already a decision made and implementation details need to be added. The ADR should document what the collective consensus for the specific issue is and how to solve it. -1. Every ADR should start with either an RFC or discussion where consensus has been met. +1. Every ADR should start with either an RFC or a discussion where consensus has been met. 2. Once consensus is met, a GitHub Pull Request (PR) is created with a new document based on the `adr-template.md`. @@ -44,9 +44,9 @@ DRAFT -> PROPOSED -> LAST CALL yyyy-mm-dd -> ACCEPTED | REJECTED -> SUPERSEDED b ABANDONED ``` -* `DRAFT`: [optional] an ADR which is work in progress, not being ready for a general review. This is to present an early work and get an early feedback in a Draft Pull Request form. -* `PROPOSED`: an ADR covering a full solution architecture and still in the review - project stakeholders haven't reached an agreed yet. -* `LAST CALL `: [optional] clear notify that we are close to accept updates. Changing a status to `LAST CALL` means that social consensus (of Cosmos SDK maintainers) has been reached and we still want to give it a time to let the community react or analyze. +* `DRAFT`: [optional] an ADR which is a work in progress, not being ready for a general review. This is to present an early work and get early feedback in a Draft Pull Request form. +* `PROPOSED`: an ADR covering a full solution architecture and still in the review - project stakeholders haven't reached an agreement yet. +* `LAST CALL `: [optional] Notify that we are close to accepting updates. Changing a status to `LAST CALL` means that social consensus (of Cosmos SDK maintainers) has been reached and we still want to give it a time to let the community react or analyze. * `ACCEPTED`: ADR which will represent a currently implemented or to be implemented architecture design. * `REJECTED`: ADR can go from PROPOSED or ACCEPTED to rejected if the consensus among project stakeholders will decide so. * `SUPERSEDED by ADR-xxx`: ADR which has been superseded by a new ADR. diff --git a/docs/architecture/adr-002-docs-structure.md b/docs/architecture/adr-002-docs-structure.md index 5819151fc1dc..aea7d60e8638 100644 --- a/docs/architecture/adr-002-docs-structure.md +++ b/docs/architecture/adr-002-docs-structure.md @@ -40,7 +40,7 @@ docs/ The files in each sub-folders do not matter and will likely change. What matters is the sectioning: * `README`: Landing page of the docs. -* `intro`: Introductory material. Goal is to have a short explainer of the Cosmos SDK and then channel people to the resource they need. The [Cosmos SDK tutorial](https://github.com/cosmos/sdk-application-tutorial/) will be highlighted, as well as the `godocs`. +* `intro`: Introductory material. Goal is to have a short explainer of the Cosmos SDK and then channel people to the resources they need. The [Cosmos SDK tutorial](https://github.com/cosmos/sdk-application-tutorial/) will be highlighted, as well as the `godocs`. * `concepts`: Contains high-level explanations of the abstractions of the Cosmos SDK. It does not contain specific code implementation and does not need to be updated often. **It is not an API specification of the interfaces**. API spec is the `godoc`. * `clients`: Contains specs and info about the various Cosmos SDK clients. * `spec`: Contains specs of modules, and others. @@ -69,7 +69,7 @@ Accepted * The `/docs` folder now only contains Cosmos SDK and gaia related material. Later, it will only contain Cosmos SDK related material. * Developers only have to update `/docs` folder when they open a PR (and not `/examples` for example). * Easier for developers to find what they need to update in the docs thanks to reworked architecture. -* Cleaner vuepress build for website docs. +* Cleaner `vuepress` build for website docs. * Will help build an executable doc (cf https://github.com/cosmos/cosmos-sdk/issues/2611) ### Neutral diff --git a/docs/architecture/adr-043-nft-module.md b/docs/architecture/adr-043-nft-module.md index 5968eb1305aa..40c21cd3c6d9 100644 --- a/docs/architecture/adr-043-nft-module.md +++ b/docs/architecture/adr-043-nft-module.md @@ -17,9 +17,9 @@ This ADR defines the `x/nft` module which is a generic implementation of NFTs, r * `MsgNewClass` - Receive the user's request to create a class, and call the `NewClass` of the `x/nft` module. * `MsgUpdateClass` - Receive the user's request to update a class, and call the `UpdateClass` of the `x/nft` module. -* `MsgMintNFT` - Receive the user's request to mint a nft, and call the `MintNFT` of the `x/nft` module. -* `BurnNFT` - Receive the user's request to burn a nft, and call the `BurnNFT` of the `x/nft` module. -* `UpdateNFT` - Receive the user's request to update a nft, and call the `UpdateNFT` of the `x/nft` module. +* `MsgMintNFT` - Receive the user's request to mint an NFT, and call the `MintNFT` of the `x/nft` module. +* `BurnNFT` - Receive the user's request to burn an NFT, and call the `BurnNFT` of the `x/nft` module. +* `UpdateNFT` - Receive the user's request to update an NFT, and call the `UpdateNFT` of the `x/nft` module. ## Context @@ -48,7 +48,7 @@ We create a `x/nft` module, which contains the following functionality: * Expose external `Message` interface for users to transfer ownership of their NFTs. * Query NFTs and their supply information. -The proposed module is a base module for NFT app logic. It's goal it to provide a common layer for storage, basic transfer functionality and IBC. The module should not be used as a standalone. +The proposed module is a base module for NFT app logic. Its goal is to provide a common layer for storage, basic transfer functionality and IBC. The module should not be used as a standalone. Instead an app should create a specialized module to handle app specific logic (eg: NFT ID construction, royalty), user level minting and burning. Moreover an app specialized module should handle auxiliary data to support the app logic (eg indexes, ORM, business data). All data carried over IBC must be part of the `NFT` or `Class` type described below. The app specific NFT data should be encoded in `NFT.data` for cross-chain integrity. Other objects related to NFT, which are not important for integrity can be part of the app specific module. @@ -58,7 +58,7 @@ All data carried over IBC must be part of the `NFT` or `Class` type described be We propose two main types: * `Class` -- describes NFT class. We can think about it as a smart contract address. -* `NFT` -- object representing unique, non fungible asset. Each NFT is associated with a Class. +* `NFT` -- object representing unique, non-fungible asset. Each NFT is associated with a class. #### Class @@ -81,7 +81,7 @@ message Class { * `symbol` is the symbol usually shown on exchanges for the NFT class; _optional_ * `description` is a detailed description of the NFT class; _optional_ * `uri` is a URI for the class metadata stored off chain. It should be a JSON file that contains metadata about the NFT class and NFT data schema ([OpenSea example](https://docs.opensea.io/docs/contract-level-metadata)); _optional_ -* `uri_hash` is a hash of the document pointed by uri; _optional_ +* `uri_hash` is a hash of the document pointed by URI; _optional_ * `data` is app specific metadata of the class; _optional_ #### NFT @@ -107,7 +107,7 @@ message NFT { * `uri` is a URI for the NFT metadata stored off chain. Should point to a JSON file that contains metadata about this NFT (Ref: [ERC721 standard and OpenSea extension](https://docs.opensea.io/docs/metadata-standards)); _required_ * `uri_hash` is a hash of the document pointed by uri; _optional_ -* `data` is an app specific data of the NFT. CAN be used by composing modules to specify additional properties of the NFT; _optional_ +* `data` is an app specific data of the NFT. Can be used by composing modules to specify additional properties of the NFT; _optional_ This ADR doesn't specify values that `data` can take; however, best practices recommend upper-level NFT modules clearly specify their contents. Although the value of this field doesn't provide the additional context required to manage NFT records, which means that the field can technically be removed from the specification, the field's existence allows basic informational/UI functionality. diff --git a/docs/architecture/adr-053-go-module-refactoring.md b/docs/architecture/adr-053-go-module-refactoring.md index d15c390191cc..a58d9ce021bc 100644 --- a/docs/architecture/adr-053-go-module-refactoring.md +++ b/docs/architecture/adr-053-go-module-refactoring.md @@ -70,7 +70,7 @@ clear improvements to be made or to remove legacy dependencies (for instance on amino or gogo proto), as long the old package attempts to avoid API breakage with aliases and wrappers * care should be taken when simply trying to turn an existing package into a -new go module: https://github.com/golang/go/wiki/Modules#is-it-possible-to-add-a-module-to-a-multi-module-repository. +new go module: https://go.dev/wiki/Modules#is-it-possible-to-add-a-module-to-a-multi-module-repository. In general, it seems safer to just create a new module path (appending v2, v3, etc. if necessary), rather than trying to make an old package a new module. diff --git a/docs/architecture/adr-069-gov-improvements.md b/docs/architecture/adr-069-gov-improvements.md index af5b12645205..1ef6971c713d 100644 --- a/docs/architecture/adr-069-gov-improvements.md +++ b/docs/architecture/adr-069-gov-improvements.md @@ -6,7 +6,7 @@ ## Status -ACCEPTED +ACCEPTED - Implemented ## Abstract diff --git a/docs/build/abci/00-introduction.md b/docs/build/abci/00-introduction.md index 6b7cd8ec3c89..7d955d41d956 100644 --- a/docs/build/abci/00-introduction.md +++ b/docs/build/abci/00-introduction.md @@ -19,7 +19,7 @@ The 5 methods introduced during ABCI 2.0 (compared to ABCI v0) are: Based on validator voting power, CometBFT chooses a block proposer and calls `PrepareProposal` on the block proposer's application (Cosmos SDK). The selected block proposer is responsible for collecting outstanding transactions from the mempool, adhering to the application's specifications. The application can enforce custom transaction ordering and incorporate additional transactions, potentially generated from vote extensions in the previous block. -To perform this manipulation on the application side, a custom handler must be implemented. By default, the Cosmos SDK provides `PrepareProposalHandler`, used in conjunction with an application specific mempool. A custom handler can be written by application developer, if a noop handler provided, all transactions are considered valid. Please see [this](https://github.com/fatal-fruit/abci-workshop) tutorial for more information on custom handlers. +To perform this manipulation on the application side, a custom handler must be implemented. By default, the Cosmos SDK provides `PrepareProposalHandler`, used in conjunction with an application specific mempool. A custom handler can be written by application developer, if a noop handler provided, all transactions are considered valid. Please note that vote extensions will only be available on the following height in which vote extensions are enabled. More information about vote extensions can be found [here](https://docs.cosmos.network/main/build/abci/vote-extensions). diff --git a/docs/build/abci/01-prepare-proposal.md b/docs/build/abci/01-prepare-proposal.md index c77c9094d450..3d480664e5a4 100644 --- a/docs/build/abci/01-prepare-proposal.md +++ b/docs/build/abci/01-prepare-proposal.md @@ -24,12 +24,12 @@ it would like the block constructed. The Cosmos SDK defines the `DefaultProposalHandler` type, which provides applications with `PrepareProposal` and `ProcessProposal` handlers. If you decide to implement your -own `PrepareProposal` handler, you must be sure to ensure that the transactions +own `PrepareProposal` handler, you must ensure that the transactions selected DO NOT exceed the maximum block gas (if set) and the maximum bytes provided by `req.MaxBytes`. ```go reference -https://github.com/cosmos/cosmos-sdk/blob/v0.50.0-alpha.0/baseapp/abci_utils.go +https://github.com/cosmos/cosmos-sdk/blob/v0.52.0-beta.1/baseapp/abci_utils.go ``` This default implementation can be overridden by the application developer in @@ -38,7 +38,7 @@ favor of a custom implementation in [`app_di.go`](https://docs.cosmos.network/ma ```go prepareOpt := func(app *baseapp.BaseApp) { abciPropHandler := baseapp.NewDefaultProposalHandler(mempool, app) - app.SetPrepareProposal(abciPropHandler.PrepareProposalHandler())) + app.SetPrepareProposal(abciPropHandler.PrepareProposalHandler()) } baseAppOptions = append(baseAppOptions, prepareOpt) diff --git a/docs/build/abci/02-process-proposal.md b/docs/build/abci/02-process-proposal.md index 834ba3b90c48..7768890bdae9 100644 --- a/docs/build/abci/02-process-proposal.md +++ b/docs/build/abci/02-process-proposal.md @@ -14,12 +14,12 @@ and `ProcessProposal` for the new proposal. Here is the implementation of the default implementation: ```go reference -https://github.com/cosmos/cosmos-sdk/blob/v0.50.0-alpha.0/baseapp/abci_utils.go#L153-L159 +https://github.com/cosmos/cosmos-sdk/blob/v0.52.0-beta.1/baseapp/abci_utils.go#L224-L231 ``` Like `PrepareProposal` this implementation is the default and can be modified by the application developer in [`app_di.go`](https://docs.cosmos.network/main/build/building-apps/app-go-di). If you decide to implement -your own `ProcessProposal` handler, you must be sure to ensure that the transactions +your own `ProcessProposal` handler, you must ensure that the transactions provided in the proposal DO NOT exceed the maximum block gas and `maxtxbytes` (if set). ```go diff --git a/docs/build/abci/03-vote-extensions.md b/docs/build/abci/03-vote-extensions.md index 59b00c89854a..26cbfd1a296d 100644 --- a/docs/build/abci/03-vote-extensions.md +++ b/docs/build/abci/03-vote-extensions.md @@ -8,7 +8,7 @@ defined in ABCI++. ## Extend Vote ABCI2.0 (colloquially called ABCI++) allows an application to extend a pre-commit vote with arbitrary data. This process does NOT have to be deterministic, and the data returned can be unique to the -validator process. The Cosmos SDK defines [`baseapp.ExtendVoteHandler`](https://github.com/cosmos/cosmos-sdk/blob/v0.50.1/types/abci.go#L26-L27): +validator process. The Cosmos SDK defines [`baseapp.ExtendVoteHandler`](https://github.com/cosmos/cosmos-sdk/blob/v0.52.0-beta.1/types/abci.go#L26-L27): ```go type ExtendVoteHandler func(Context, *abci.ExtendVoteRequest) (*abci.ExtendVoteResponse, error) @@ -35,7 +35,7 @@ Click [here](https://docs.cosmos.network/main/build/abci/vote-extensions) if you Similar to extending a vote, an application can also verify vote extensions from other validators when validating their pre-commits. For a given vote extension, -this process MUST be deterministic. The Cosmos SDK defines [`sdk.VerifyVoteExtensionHandler`](https://github.com/cosmos/cosmos-sdk/blob/v0.50.1/types/abci.go#L29-L31): +this process MUST be deterministic. The Cosmos SDK defines [`sdk.VerifyVoteExtensionHandler`](https://github.com/cosmos/cosmos-sdk/blob/v0.52.0-beta.1/types/abci.go#L29-L31): ```go type VerifyVoteExtensionHandler func(Context, *abci.VerifyVoteExtensionRequest) (*abci.VerifyVoteExtensionResponse, error) diff --git a/docs/build/abci/04-checktx.md b/docs/build/abci/04-checktx.md new file mode 100644 index 000000000000..a2c5f2d707d6 --- /dev/null +++ b/docs/build/abci/04-checktx.md @@ -0,0 +1,50 @@ +# CheckTx + +CheckTx is called by the `BaseApp` when comet receives a transaction from a client, over the p2p network or RPC. The CheckTx method is responsible for validating the transaction and returning an error if the transaction is invalid. + +```mermaid +graph TD + subgraph SDK[Cosmos SDK] + B[Baseapp] + A[AnteHandlers] + B <-->|Validate TX| A + end + C[CometBFT] <-->|CheckTx|SDK + U((User)) -->|Submit TX| C + N[P2P] -->|Receive TX| C +``` + +```go reference +https://github.com/cosmos/cosmos-sdk/blob/31c604762a434c7b676b6a89897ecbd7c4653a23/baseapp/abci.go#L350-L390 +``` + +## CheckTx Handler + +`CheckTxHandler` allows users to extend the logic of `CheckTx`. `CheckTxHandler` is called by pasding context and the transaction bytes received through ABCI. It is required that the handler returns deterministic results given the same transaction bytes. + +:::note +we return the raw decoded transaction here to avoid decoding it twice. +::: + +```go +type CheckTxHandler func(ctx sdk.Context, tx []byte) (Tx, error) +``` + +Setting a custom `CheckTxHandler` is optional. It can be done from your app.go file: + +```go +func NewSimApp( + logger log.Logger, + db corestore.KVStoreWithBatch, + traceStore io.Writer, + loadLatest bool, + appOpts servertypes.AppOptions, + baseAppOptions ...func(*baseapp.BaseApp), +) *SimApp { + ... + // Create ChecktxHandler + checktxHandler := abci.NewCustomCheckTxHandler(...) + app.SetCheckTxHandler(checktxHandler) + ... +} +``` diff --git a/docs/build/building-apps/02-app-mempool.md b/docs/build/building-apps/02-app-mempool.md index 45719af4824d..d22832b3f166 100644 --- a/docs/build/building-apps/02-app-mempool.md +++ b/docs/build/building-apps/02-app-mempool.md @@ -22,7 +22,7 @@ Notably it introduces the `PrepareProposal` and `ProcessProposal` steps of ABCI+ ## Mempool -+ Before we delve into `PrepareProposal` and `ProcessProposal`, let's first walk through the mempool concepts. +* Before we delve into `PrepareProposal` and `ProcessProposal`, let's first walk through the mempool concepts. There are countless designs that an application developer can write for a mempool, the SDK opted to provide only simple mempool implementations. Namely, the SDK provides the following mempools: diff --git a/docs/build/building-apps/03-app-upgrade.md b/docs/build/building-apps/03-app-upgrade.md index a26cdcce0fb7..b9c487534dea 100644 --- a/docs/build/building-apps/03-app-upgrade.md +++ b/docs/build/building-apps/03-app-upgrade.md @@ -41,7 +41,7 @@ and gracefully exit. Generally the application binary will restart on exit, but then will execute this BeginBlocker again and exit, causing a restart loop. Either the operator can manually install the new software, or you can make use of an external watcher daemon to possibly download and then switch binaries, -also potentially doing a backup. The SDK tool for doing such, is called [Cosmovisor](https://docs.cosmos.network/main/tooling/cosmovisor). +also potentially doing a backup. The SDK tool for doing such, is called [Cosmovisor](https://docs.cosmos.network/main/build/tooling/cosmovisor). When the binary restarts with the upgraded version (here v0.40.0), it will detect we have registered the "testnet-v2" upgrade handler in the code, and realize it is the new version. It then will run the upgrade handler @@ -131,7 +131,7 @@ to lose connectivity with the exiting nodes, thus this module prefers to just ha ## Automation -Read more about [Cosmovisor](https://docs.cosmos.network/main/tooling/cosmovisor), the tool for automating upgrades. +Read more about [Cosmovisor](https://docs.cosmos.network/main/build/tooling/cosmovisor), the tool for automating upgrades. ## Canceling Upgrades diff --git a/docs/build/building-apps/05-app-testnet.md b/docs/build/building-apps/05-app-testnet.md index d773ffd4ed9f..c96e229e2806 100644 --- a/docs/build/building-apps/05-app-testnet.md +++ b/docs/build/building-apps/05-app-testnet.md @@ -13,10 +13,10 @@ We allow developers to take the state from their mainnet and run tests against t We will be breaking down the steps to create a testnet from mainnet state. ```go - // InitMerlinAppForTestnet is broken down into two sections: + // InitSimAppForTestnet is broken down into two sections: // Required Changes: Changes that, if not made, will cause the testnet to halt or panic // Optional Changes: Changes to customize the testnet to one's liking (lower vote times, fund accounts, etc) - func InitMerlinAppForTestnet(app *MerlinApp, newValAddr bytes.HexBytes, newValPubKey crypto.PubKey, newOperatorAddress, upgradeToTrigger string) *MerlinApp { + func InitSimAppForTestnet(app *SimApp, newValAddr bytes.HexBytes, newValPubKey crypto.PubKey, newOperatorAddress, upgradeToTrigger string) *SimApp { ... } ``` @@ -137,7 +137,7 @@ It is useful to create new accounts for your testing purposes. This avoids the n defaultCoins := sdk.NewCoins(sdk.NewInt64Coin("ustake", 1000000000000)) - localMerlinAccounts := []sdk.AccAddress{ + localSimAppAccounts := []sdk.AccAddress{ sdk.MustAccAddressFromBech32("cosmos12smx2wdlyttvyzvzg54y2vnqwq2qjateuf7thj"), sdk.MustAccAddressFromBech32("cosmos1cyyzpxplxdzkeea7kwsydadg87357qnahakaks"), sdk.MustAccAddressFromBech32("cosmos18s5lynnmx37hq4wlrw9gdn68sg2uxp5rgk26vv"), @@ -151,8 +151,8 @@ It is useful to create new accounts for your testing purposes. This avoids the n sdk.MustAccAddressFromBech32("cosmos14gs9zqh8m49yy9kscjqu9h72exyf295afg6kgk"), sdk.MustAccAddressFromBech32("cosmos1jllfytsz4dryxhz5tl7u73v29exsf80vz52ucc")} - // Fund localMerlin accounts - for _, account := range localMerlinAccounts { + // Fund localSimApp accounts + for _, account := range localSimAppAccounts { err := app.BankKeeper.MintCoins(ctx, minttypes.ModuleName, defaultCoins) if err != nil { tmos.Exit(err.Error()) @@ -195,7 +195,7 @@ Before we can run the testnet we must plug everything together. in `root.go`, in the `initRootCmd` function we add: ```diff -server.AddCommands(rootCmd, simapp.DefaultNodeHome, newApp, createMerlinAppAndExport) +server.AddCommands(rootCmd, simapp.DefaultNodeHome, newApp, createSimAppAndExport) +server.AddTestnetCreatorCommand(rootCmd, simapp.DefaultNodeHome, newTestnetApp) ``` @@ -205,7 +205,7 @@ Next we will add a newTestnetApp helper function: // newTestnetApp starts by running the normal newApp method. From there, the app interface returned is modified in order // for a testnet to be created from the provided app. func newTestnetApp(logger log.Logger, db cometbftdb.DB, traceStore io.Writer, appOpts servertypes.AppOptions) servertypes.Application { - // Create an app and type cast to an MerlinApp + // Create an app and type cast to an SimApp app := newApp(logger, db, traceStore, appOpts) simApp, ok := app.(*simapp.SimApp) if !ok { @@ -229,7 +229,7 @@ func newTestnetApp(logger log.Logger, db cometbftdb.DB, traceStore io.Writer, ap panic("upgradeToTrigger is not of type string") } - // Make modifications to the normal MerlinApp required to run the network locally - return meriln.InitMerlinAppForTestnet(simApp, newValAddr, newValPubKey, newOperatorAddress, upgradeToTrigger) + // Make modifications to the normal SimApp required to run the network locally + return simapp.InitSimAppForTestnet(simApp, newValAddr, newValPubKey, newOperatorAddress, upgradeToTrigger) } ``` diff --git a/docs/build/building-apps/06-app-go-genesis.md b/docs/build/building-apps/06-app-go-genesis.md new file mode 100644 index 000000000000..b9902858d7fe --- /dev/null +++ b/docs/build/building-apps/06-app-go-genesis.md @@ -0,0 +1,47 @@ +--- +sidebar_position: 1 +--- + +### Modifying the `DefaultGenesis` + +It is possible to modify the DefaultGenesis parameters for modules by wrapping the module, providing it to the `*module.Manager` and injecting it with `depinject`. + +Example ( staking ) : + +```go +type CustomStakingModule struct { + staking.AppModule + cdc codec.Codec +} + +// DefaultGenesis will override the Staking module DefaultGenesis AppModuleBasic method. +func (cm CustomStakingModule) DefaultGenesis() json.RawMessage { + params := stakingtypes.DefaultParams() + params.BondDenom = "mydenom" + + return cm.cdc.MustMarshalJSON(&stakingtypes.GenesisState{ + Params: params, + }) +} + +// option 1 ( for depinject users ): override previous module manager +depinject.Inject( +// ... provider/invoker/supplier +&moduleManager, +) + +oldStakingModule,_ := moduleManager.Modules()[stakingtypes.ModuleName].(staking.AppModule) +moduleManager.Modules()[stakingtypes.ModuleName] = CustomStakingModule{ + AppModule: oldStakingModule, + cdc: appCodec, +} + +// option 2 ( for non depinject users ): use new module manager +moduleManager := module.NewManagerFromMap(map[string]appmodule.AppModule{ +stakingtypes.ModuleName: CustomStakingModule{cdc: appCodec, AppModule: staking.NewAppModule(...)}, +// other modules ... +}) + +// set the module manager +app.ModuleManager = moduleManager +``` diff --git a/docs/build/building-apps/06-system-tests.md b/docs/build/building-apps/06-system-tests.md new file mode 100644 index 000000000000..eb6d61ffea46 --- /dev/null +++ b/docs/build/building-apps/06-system-tests.md @@ -0,0 +1,58 @@ +--- +sidebar_position: 1 +--- + +# System Tests + +System tests provide a framework to write and execute black box tests against a running chain. This adds another level +of confidence on top of unit, integration, and simulations tests, ensuring that business-critical scenarios +(like double signing prevention) or scenarios that can't be tested otherwise (like a chain upgrade) are covered. + +## Vanilla Go for Flow Control + +System tests are vanilla Go tests that interact with the compiled chain binary. The `test runner` component starts a +local testnet of 4 nodes (by default) and provides convenient helper methods for accessing the +`system under test (SUT)`. +A `CLI wrapper` makes it easy to access keys, submit transactions, or execute operations. Together, these components +enable the replication and validation of complex business scenarios. + +Here's an example of a double signing test, where a new node is added with the same key as the first validator: +[double signing test example](https://github.com/cosmos/cosmos-sdk/blob/v0.52.0-beta.1/tests/systemtests/fraud_test.go) + +The [getting started tutorial](https://github.com/cosmos/cosmos-sdk/blob/v0.52.0-beta.1/tests/systemtests/getting_started.md) +contains a step-by-step guide to building and running your first system test. It covers setting chain state via genesis +or +transactions and validation via transaction response or queries. + +## Design Principles and Guidelines + +System tests are slower compared to unit or integration tests as they interact with a running chain. Therefore, certain +principles can guide their usage: + +- **Perspective:** Tests should mimic a human interacting with the chain from the outside. Initial states can be set via + genesis or transactions to support a test scenario. +- **Roles:** The user can have multiple roles such as validator, delegator, granter, or group admin. +- **Focus:** Tests should concentrate on happy paths or business-critical workflows. Unit and integration tests are + better suited for more fine-grained testing. +- **Workflows:** Test workflows and scenarios, not individual units. Given the high setup costs, it is reasonable to + combine multiple steps and assertions in a single test method. +- **Genesis Mods:** Genesis modifications can incur additional time costs for resetting dirty states. Reuse existing + accounts (node0..n) whenever possible. +- **Framework:** Continuously improve the framework for better readability and reusability. + +## Errors and Debugging + +All output is logged to `systemtests/testnet/node{0..n}.out`. Usually, `node0.out` is very noisy as it receives the CLI +connections. Prefer any other node's log to find stack traces or error messages. + +Using system tests for state setup during debugging has become very handy: + +- Start the test with one node only and verbose output: + + ```sh + go test -v -tags=system_test ./ --run TestAccountCreation --verbose --nodes-count=1 + ``` + +- Copy the CLI command for the transaction and modify the test to stop before the command +- Start the node with `--home=/tests/systemtests/testnet/node0//` in debug mode +- Execute CLI command from shell and enter breakpoints diff --git a/docs/build/building-modules/06-beginblock-endblock.md b/docs/build/building-modules/06-beginblock-endblock.md index 51b72b7f056c..21c1a3303d3f 100644 --- a/docs/build/building-modules/06-beginblock-endblock.md +++ b/docs/build/building-modules/06-beginblock-endblock.md @@ -24,7 +24,7 @@ When needed, `BeginBlocker` and `EndBlocker` are implemented as part of the [`Ha The actual implementation of `BeginBlocker` and `EndBlocker` in `abci.go` are very similar to that of a [`Msg` service](./03-msg-services.md): -* They generally use the [`keeper`](./06-keeper.md) and [`ctx`](../../learn/advanced/02-context.md) to retrieve information about the latest state. +* They generally use the [`keeper`](./06-keeper.md) and [`ctx`](https://pkg.go.dev/context) to retrieve information about the latest state. * If needed, they use the `keeper` and `ctx` to trigger state-transitions. * If needed, they can emit [`events`](../../learn/advanced/08-events.md) via the `environments`'s `EventManager`. @@ -35,13 +35,20 @@ It is possible for developers to define the order of execution between the `Begi See an example implementation of `BeginBlocker` from the `distribution` module: ```go reference -https://github.com/cosmos/cosmos-sdk/blob/v0.50.0-alpha.0/x/distribution/abci.go#L14-L38 +https://github.com/cosmos/cosmos-sdk/blob/v0.52.0-beta.1/x/distribution/keeper/abci.go#L13-L40 ``` -and an example implementation of `EndBlocker` from the `staking` module: +and an example of `EndBlocker` from the `gov` module: ```go reference -https://github.com/cosmos/cosmos-sdk/blob/v0.50.0-alpha.0/x/staking/keeper/abci.go#L22-L27 +https://github.com/cosmos/cosmos-sdk/blob/v0.52.0-beta.1/x/gov/keeper/abci.go#L22 ``` +and an example implementation of `EndBlocker` with validator updates from the `staking` module: + +```go reference +https://github.com/cosmos/cosmos-sdk/blob/v0.52.0-beta.1/x/staking/keeper/abci.go#L12-L17 +``` + + diff --git a/docs/build/building-modules/06-keeper.md b/docs/build/building-modules/06-keeper.md index 1302a46d6324..0bd776ff9b9d 100644 --- a/docs/build/building-modules/06-keeper.md +++ b/docs/build/building-modules/06-keeper.md @@ -41,14 +41,14 @@ type Keeper struct { For example, here is the type definition of the `keeper` from the `staking` module: ```go reference -https://github.com/cosmos/cosmos-sdk/blob/v0.50.0-alpha.0/x/staking/keeper/keeper.go#L23-L31 +https://github.com/cosmos/cosmos-sdk/blob/v0.52.0-beta.1/x/staking/keeper/keeper.go#L54-L115 ``` Let us go through the different parameters: * An expected `keeper` is a `keeper` external to a module that is required by the internal `keeper` of said module. External `keeper`s are listed in the internal `keeper`'s type definition as interfaces. These interfaces are themselves defined in an `expected_keepers.go` file in the root of the module's folder. In this context, interfaces are used to reduce the number of dependencies, as well as to facilitate the maintenance of the module itself. * `KVStoreService`s grant access to the store(s) of the [multistore](../../learn/advanced/04-store.md) managed by the module. They should always remain unexposed to external modules. -* `cdc` is the [codec](../../learn/advanced/05-encoding.md) used to marshall and unmarshall structs to/from `[]byte`. The `cdc` can be any of `codec.BinaryCodec`, `codec.JSONCodec` or `codec.Codec` based on your requirements. It can be either a proto or amino codec as long as they implement these interfaces. +* `cdc` is the [codec](../../learn/advanced/05-encoding.md) used to marshal and unmarshal structs to/from `[]byte`. The `cdc` can be any of `codec.BinaryCodec`, `codec.JSONCodec` or `codec.Codec` based on your requirements. It can be either a proto or amino codec as long as they implement these interfaces. * The authority listed is a module account or user account that has the right to change module level parameters. Previously this was handled by the param module, which has been deprecated. Of course, it is possible to define different types of internal `keeper`s for the same module (e.g. a read-only `keeper`). Each type of `keeper` comes with its own constructor function, which is called from the [application's constructor function](../../learn/beginner/00-app-anatomy.md). This is where `keeper`s are instantiated, and where developers make sure to pass correct instances of modules' `keeper`s to other modules that require them. @@ -60,3 +60,10 @@ Of course, it is possible to define different types of internal `keeper`s for th State management is recommended to be done via [Collections](../packages/collections) + +## State Management + +In the Cosmos SDK, it is crucial to be methodical and selective when managing state within a module, as improper state management can lead to inefficiency, security risks, and scalability issues. Not all data belongs in the on-chain state; it's important to store only essential blockchain data that needs to be verified by consensus. Storing unnecessary information, especially client-side data, can bloat the state and slow down performance. Instead, developers should focus on using an off-chain database to handle supplementary data, extending the API as needed. This approach minimizes on-chain complexity, optimizes resource usage, and keeps the blockchain state lean and efficient, ensuring scalability and smooth operations. + + +The Cosmos SDK leverages Protocol Buffers (protobuf) for efficient state management, providing a well-structured, binary encoding format that ensures compatibility and performance across different modules. The SDK’s recommended approach for managing state is through the [collections package](../pacakges/02-collections.md), which simplifies state handling by offering predefined data structures like maps and indexed sets, reducing the complexity of managing raw state data. While users can opt for custom encoding schemes if they need more flexibility or have specialized requirements, they should be aware that such custom implementations may not integrate seamlessly with indexers that decode state data on the fly. This could lead to challenges in data retrieval, querying, and interoperability, making protobuf a safer and more future-proof choice for most use cases. diff --git a/docs/build/building-modules/12-errors.md b/docs/build/building-modules/12-errors.md index b6935e62666e..20c7c512173d 100644 --- a/docs/build/building-modules/12-errors.md +++ b/docs/build/building-modules/12-errors.md @@ -14,6 +14,10 @@ common or general errors which can be further wrapped to provide additional spec There are two ways to return errors. You can register custom errors with a codespace that is meant to provide more information to clients and normal go errors. The Cosmos SDK uses a mixture of both. +:::Note +Errors v2 has been created as a zero dependency errors package. GRPC errors and tracing support is removed natively from the errors package. Users are required to wrap stack traces and add tracing information to their errors. +::: + :::Warning If errors are registered they are part of consensus and cannot be changed in a minor release ::: diff --git a/docs/build/building-modules/14-simulator.md b/docs/build/building-modules/14-simulator.md index 0d8b4c5a861a..966df4cb8952 100644 --- a/docs/build/building-modules/14-simulator.md +++ b/docs/build/building-modules/14-simulator.md @@ -38,6 +38,8 @@ and then unmarshals the value from the `KVPair` to the type provided. You can use the example [here](https://github.com/cosmos/cosmos-sdk/blob/main/x/distribution/simulation/decoder.go) from the distribution module to implement your store decoders. +If the module uses the `collections` package, you can use the example [here](https://github.com/cosmos/cosmos-sdk/blob/23cf89cce1882ba9c8280e64735ae200504bfdce/x/bank/module.go#L166) from the Bank module to implement your store decoders. + ### Randomized genesis The simulator tests different scenarios and values for genesis parameters @@ -61,33 +63,33 @@ Operations on the simulation are simulated using the full [transaction cycle](.. Shown below is how weights are set: ```go reference -https://github.com/cosmos/cosmos-sdk/blob/release/v0.50.x/x/staking/simulation/operations.go#L19-L86 +https://github.com/cosmos/cosmos-sdk/blob/23cf89cce1882ba9c8280e64735ae200504bfdce/x/staking/depinject.go#L144-L154 ``` As you can see, the weights are predefined in this case. Options exist to override this behavior with different weights. One option is to use `*rand.Rand` to define a random weight for the operation, or you can inject your own predefined weights. -Here is how one can override the above package `simappparams`. - -```go reference -https://github.com/cosmos/cosmos-sdk/blob/release/v0.51.x/Makefile#L292-L334 -``` - The SDK simulations can be executed like normal tests in Go from the shell or within an IDE. Make sure that you pass the `-tags='sims` parameter to enable them and other params that make sense for your scenario. +```go reference +https://github.com/cosmos/cosmos-sdk/blob/23cf89cce1882ba9c8280e64735ae200504bfdce/scripts/build/simulations.mk#L19 +``` ### Random proposal contents Randomized governance proposals are also supported on the Cosmos SDK simulator. Each -module must define the governance proposal `Content`s that they expose and register -them to be used on the parameters. +module must register the message to be used for governance proposals. + +```go reference +https://github.com/cosmos/cosmos-sdk/blob/23cf89cce1882ba9c8280e64735ae200504bfdce/x/staking/depinject.go#L139-L142 +``` ## Registering simulation functions Now that all the required functions are defined, we need to integrate them into the module pattern within the `module.go`: ```go reference -https://github.com/cosmos/cosmos-sdk/blob/release/v0.50.x/x/distribution/module.go#L180-L203 +https://github.com/cosmos/cosmos-sdk/blob/23cf89cce1882ba9c8280e64735ae200504bfdce/x/staking/depinject.go#L127-L154 ``` ## App Simulator manager @@ -117,7 +119,7 @@ func NewCustomApp(...) { gov.NewAppModule(app.govKeeper, app.accountKeeper, app.supplyKeeper), mint.NewAppModule(app.mintKeeper), distr.NewAppModule(app.distrKeeper, app.accountKeeper, app.supplyKeeper, app.stakingKeeper), - staking.NewAppModule(app.stakingKeeper, app.accountKeeper, app.supplyKeeper), + staking.NewAppModule(cdc, app.stakingKeeper), slashing.NewAppModule(app.slashingKeeper, app.accountKeeper, app.stakingKeeper), ) @@ -133,5 +135,5 @@ The simulations provide deterministic behaviour already. The integration with th can be done at a high level with the deterministic pseudo random number generator where the fuzzer provides varying numbers. ```go reference -https://github.com/cosmos/cosmos-sdk/blob/release/v0.51.x/Makefile#L352-L355 +https://github.com/cosmos/cosmos-sdk/blob/23cf89cce1882ba9c8280e64735ae200504bfdce/scripts/build/simulations.mk#L80-L84 ``` diff --git a/docs/build/building-modules/16-testing.md b/docs/build/building-modules/16-testing.md index f2fafa36fd9d..65ed52a8a142 100644 --- a/docs/build/building-modules/16-testing.md +++ b/docs/build/building-modules/16-testing.md @@ -86,38 +86,26 @@ https://github.com/cosmos/cosmos-sdk/blob/v0.50.0-alpha.0/tests/integration/bank ## Simulations -Simulations uses as well a minimal application, built with [`depinject`](../packages/01-depinject.md): +Simulations fuzz tests for deterministic message execution. They use a minimal application, built with [`depinject`](../packages/01-depinject.md): :::note -You can as well use the `AppConfig` `configurator` for creating an `AppConfig` [inline](https://github.com/cosmos/cosmos-sdk/blob/v0.50.0-alpha.0/x/slashing/app_test.go#L54-L62). There is no difference between those two ways, use whichever you prefer. +Simulations have been refactored to message factories ::: -Following is an example for `x/gov/` simulations: +An example for `x/bank/` simulations: ```go reference -https://github.com/cosmos/cosmos-sdk/blob/v0.50.0-alpha.0/x/gov/simulation/operations_test.go#L406-L430 +https://github.com/cosmos/cosmos-sdk/blob/release/v0.52.x/x/bank/simulation/msg_factory.go#L13-L20 ``` -```go reference -https://github.com/cosmos/cosmos-sdk/blob/v0.50.0-alpha.0/x/gov/simulation/operations_test.go#L90-L132 -``` - -## End-to-end Tests +## System Tests -End-to-end tests are at the top of the [test pyramid](https://martinfowler.com/articles/practical-test-pyramid.html). -They must test the whole application flow, from the user perspective (for instance, CLI tests). They are located under [`/tests/e2e`](https://github.com/cosmos/cosmos-sdk/tree/main/tests/e2e). +System tests are at the top of the [test pyramid](https://martinfowler.com/articles/practical-test-pyramid.html). +They test the whole application flow as black box, from the user perspective. They are located under [`/tests/systemtests`](https://github.com/cosmos/cosmos-sdk/tree/main/tests/systemtests). - -For that, the SDK is using `simapp` but you should use your own application (`appd`). -Here are some examples: +For that, the SDK is using the `simapp` binary, but you should use your own binary. +More details about system test can be found in [building-apps](https://docs.cosmos.network/main/build/building-apps/06-system-tests.md) -* SDK E2E tests: . -* Cosmos Hub E2E tests: . -* Osmosis E2E tests: . - -:::note warning -The SDK is in the process of creating its E2E tests, as defined in [ADR-59](https://docs.cosmos.network/main/build/architecture/adr-059-test-scopes). This page will eventually be updated with better examples. -::: ## Learn More diff --git a/docs/build/packages/README.md b/docs/build/packages/README.md index d7a115b263de..cbb150f501b3 100644 --- a/docs/build/packages/README.md +++ b/docs/build/packages/README.md @@ -9,31 +9,45 @@ It lists all standalone Go modules that are part of the Cosmos SDK. :::tip For more information on SDK modules, see the [SDK Modules](https://docs.cosmos.network/main/modules) section. -For more information on SDK tooling, see the [Tooling](https://docs.cosmos.network/main/tooling) section. +For more information on SDK tooling, see the [Tooling](https://docs.cosmos.network/main/build/tooling) section. ::: ## Core -* [Core](https://pkg.go.dev/cosmossdk.io/core) - Core library defining SDK interfaces ([ADR-063](https://docs.cosmos.network/main/architecture/adr-063-core-module-api)) +* [Core](https://pkg.go.dev/cosmossdk.io/core) - Core library defining SDK modules and Server core interfaces ([ADR-063](https://docs.cosmos.network/main/architecture/adr-063-core-module-api)) * [API](https://pkg.go.dev/cosmossdk.io/api) - API library containing generated SDK Pulsar API * [Store](https://pkg.go.dev/cosmossdk.io/store) - Implementation of the Cosmos SDK store +* [Store/v2](https://pkg.go.dev/cosmossdk.io/store/v2) - Implementation of the Cosmos SDK store + +## V2 + +* [Server/v2/stf](https://pkg.go.dev/cosmossdk.io/server/v2/stf) - State Transition Function (STF) library for Cosmos SDK v2 +* [Server/v2/appmanager](https://pkg.go.dev/cosmossdk.io/server/v2/appmanager) - App coordinator for Cosmos SDK v2 +* [runtime/v2](https://pkg.go.dev/cosmossdk.io/runtime/v2) - Runtime library for Cosmos SDK v2 +* [Server/v2](https://pkg.go.dev/cosmossdk.io/server/v2) - Global server library for Cosmos SDK v2 +* [Server/v2/cometbft](https://pkg.go.dev/cosmossdk.io/server/v2/cometbft) - CometBFT Server implementation for Cosmos SDK v2 ## State Management * [Collections](./02-collections.md) - State management library * [ORM](./03-orm.md) - State management library +* [Schema](https://pkg.go.dev/cosmossdk.io/schema) - Logical representation of module state schemas +* [PostgreSQL indexer](https://pkg.go.dev/cosmossdk.io/indexer/postgres) - PostgreSQL indexer for Cosmos SDK modules -## Automation +## UX * [Depinject](./01-depinject.md) - Dependency injection framework * [Client/v2](https://pkg.go.dev/cosmossdk.io/client/v2) - Library powering [AutoCLI](https://docs.cosmos.network/main/core/autocli) ## Utilities +* [Core/Testing](https://pkg.go.dev/cosmossdk.io/core/testing) - Mocking library for SDK modules * [Log](https://pkg.go.dev/cosmossdk.io/log) - Logging library * [Errors](https://pkg.go.dev/cosmossdk.io/errors) - Error handling library +* [Errors/v2](https://pkg.go.dev/cosmossdk.io/errors/v2) - Error handling library * [Math](https://pkg.go.dev/cosmossdk.io/math) - Math library for SDK arithmetic operations ## Example +* [SimApp v2](https://pkg.go.dev/cosmossdk.io/simapp/v2) - SimApp/v2 is **the** sample Cosmos SDK v2 chain. This package should not be imported in your application. * [SimApp](https://pkg.go.dev/cosmossdk.io/simapp) - SimApp is **the** sample Cosmos SDK chain. This package should not be imported in your application. diff --git a/docs/build/tooling/00-protobuf.md b/docs/build/tooling/00-protobuf.md index 01afbb342c15..849a7974eab7 100644 --- a/docs/build/tooling/00-protobuf.md +++ b/docs/build/tooling/00-protobuf.md @@ -4,21 +4,17 @@ sidebar_position: 1 # Protocol Buffers -It is known that Cosmos SDK uses protocol buffers extensively, this document is meant to provide a guide on how it is used in the cosmos-sdk. +Cosmos SDK uses protocol buffers extensively, this document is meant to provide a guide on how it is used in the cosmos-sdk. -To generate the proto file, the Cosmos SDK uses a docker image, this image is provided to all to use as well. The latest version is `ghcr.io/cosmos/proto-builder:0.12.x` +To generate the proto file, the Cosmos SDK uses a docker image, this image is provided to all to use as well. The latest version is `ghcr.io/cosmos/proto-builder:0.15.x` Below is the example of the Cosmos SDK's commands for generating, linting, and formatting protobuf files that can be reused in any applications makefile. ```go reference -https://github.com/cosmos/cosmos-sdk/blob/v0.50.0-alpha.0/Makefile#L411-L432 +https://github.com/cosmos/cosmos-sdk/blob/v0.52.0-beta.1/scripts/build/protobuf.mk#L1-L10 ``` -The script used to generate the protobuf files can be found in the `scripts/` directory. - -```shell reference -https://github.com/cosmos/cosmos-sdk/blob/v0.50.0-alpha.0/scripts/protocgen.sh -``` +The [`protocgen.sh`](https://github.com/cosmos/cosmos-sdk/blob/v0.52.0-beta.1/scripts/protocgen.sh) script used to generate the protobuf files via buf can be found in the `scripts/` directory. ## Buf @@ -36,7 +32,9 @@ https://github.com/cosmos/cosmos-sdk/blob/main/buf.work.yaml#L6-L9 ### Proto Directory -Next is the `proto/` directory where all of our protobuf files live. In here there are many different buf files defined each serving a different purpose. +The `proto/` directory where all of global protobuf files live. +In here there are many different buf files defined each serving a different purpose. +Modules proto files are defined in their respective module directories (in the SDK `x/{moduleName}/proto`). ```bash ├── README.md @@ -50,8 +48,6 @@ Next is the `proto/` directory where all of our protobuf files live. In here the └── tendermint ``` -The above diagram all the files and directories within the Cosmos SDK `proto/` directory. - #### `buf.gen.gogo.yaml` `buf.gen.gogo.yaml` defines how the protobuf files should be generated for use with in the module. This file uses [gogoproto](https://github.com/gogo/protobuf), a separate generator from the google go-proto generator that makes working with various objects more ergonomic, and it has more performant encode and decode steps @@ -60,10 +56,6 @@ The above diagram all the files and directories within the Cosmos SDK `proto/` d https://github.com/cosmos/cosmos-sdk/blob/main/proto/buf.gen.gogo.yaml#L1-L9 ``` -:::tip -Example of how to define `gen` files can be found [here](https://docs.buf.build/tour/generate-go-code) -::: - #### `buf.gen.pulsar.yaml` `buf.gen.pulsar.yaml` defines how protobuf files should be generated using the [new golang apiv2 of protobuf](https://go.dev/blog/protobuf-apiv2). This generator is used instead of the google go-proto generator because it has some extra helpers for Cosmos SDK applications and will have more performant encode and decode than the google go-proto generator. You can follow the development of this generator [here](https://github.com/cosmos/cosmos-proto). @@ -72,10 +64,6 @@ Example of how to define `gen` files can be found [here](https://docs.buf.build/ https://github.com/cosmos/cosmos-sdk/blob/main/proto/buf.gen.pulsar.yaml#L1-L18 ``` -:::tip -Example of how to define `gen` files can be found [here](https://docs.buf.build/tour/generate-go-code) -::: - #### `buf.gen.swagger.yaml` `buf.gen.swagger.yaml` generates the swagger documentation for the query and messages of the chain. This will only define the REST API end points that were defined in the query and msg servers. You can find examples of this [here](https://github.com/cosmos/cosmos-sdk/blob/main/x/bank/proto/cosmos/bank/v1beta1/query.proto) @@ -84,10 +72,6 @@ Example of how to define `gen` files can be found [here](https://docs.buf.build/ https://github.com/cosmos/cosmos-sdk/blob/main/proto/buf.gen.swagger.yaml#L1-L6 ``` -:::tip -Example of how to define `gen` files can be found [here](https://docs.buf.build/tour/generate-go-code) -::: - #### `buf.lock` This is an autogenerated file based off the dependencies required by the `.gen` files. There is no need to copy the current one. If you depend on cosmos-sdk proto definitions a new entry for the Cosmos SDK will need to be provided. The dependency you will need to use is `buf.build/cosmos/cosmos-sdk`. @@ -98,16 +82,13 @@ https://github.com/cosmos/cosmos-sdk/blob/main/proto/buf.lock#L1-L16 #### `buf.yaml` -`buf.yaml` defines the [name of your package](https://github.com/cosmos/cosmos-sdk/blob/main/proto/buf.yaml#L3), which [breakage checker](https://docs.buf.build/tour/detect-breaking-changes) to use and how to [lint your protobuf files](https://buf.build/docs/tutorials/getting-started-with-buf-cli#lint-your-api). +`buf.yaml` defines the [name of your package](https://github.com/cosmos/cosmos-sdk/blob/main/proto/buf.yaml#L3), which [breakage checker](https://buf.build/docs/tutorials/getting-started-with-buf-cli#detect-breaking-changes) to use and how to [lint your protobuf files](https://buf.build/docs/tutorials/getting-started-with-buf-cli#lint-your-api). + +It is advised to use a tagged version of the buf modules corresponding to the version of the Cosmos SDK being are used. ```go reference https://github.com/cosmos/cosmos-sdk/blob/main/proto/buf.yaml#L1-L24 ``` We use a variety of linters for the Cosmos SDK protobuf files. The repo also checks this in ci. - A reference to the github actions can be found [here](https://github.com/cosmos/cosmos-sdk/blob/main/.github/workflows/proto.yml#L1-L32) - -```go reference -https://github.com/cosmos/cosmos-sdk/blob/main/.github/workflows/proto.yml#L1-L32 -``` diff --git a/docs/learn/advanced/05-encoding.md b/docs/learn/advanced/05-encoding.md index 6df0dda2ec14..4a3af677d61d 100644 --- a/docs/learn/advanced/05-encoding.md +++ b/docs/learn/advanced/05-encoding.md @@ -47,7 +47,7 @@ via Protobuf. This means that modules may use Protobuf encoding, but the types m implement `ProtoMarshaler`. If modules wish to avoid implementing this interface for their types, this is autogenerated via [buf](https://buf.build/) -If modules use [Collections](../../build/packages/02-collections.md) or [ORM](../../build/packages/03-orm.md), encoding and decoding are handled, marshal and unmarshal should not be handled manually unless for specific cases identified by the developer. +Modules are recommended to use [collections](../../build/packages/02-collections.md) for handling encoding and decoding of state. Usage of collections handles marshal and unmarshal for you. By default protobuf is used but other encodings can be used if preferred. ### Gogoproto @@ -78,15 +78,15 @@ the consensus engine accepts only transactions in the form of raw bytes. * The `TxDecoder` object performs the decoding. ```go reference -https://github.com/cosmos/cosmos-sdk/blob/v0.50.0-alpha.0/types/tx_msg.go#L91-L95 +https://github.com/cosmos/cosmos-sdk/blob/v0.52.0-beta.1/types/tx_msg.go#L91-L95 ``` A standard implementation of both these objects can be found in the [`auth/tx` module](https://docs.cosmos.network/main/build/modules/auth#transactions): -https://github.com/cosmos/cosmos-sdk/blob/v0.50.0-alpha.0/x/auth/tx/decoder.go +https://github.com/cosmos/cosmos-sdk/blob/v0.52.0-beta.1/x/auth/tx/decoder.go ```go reference -https://github.com/cosmos/cosmos-sdk/blob/v0.50.0-alpha.0/x/auth/tx/encoder.go +https://github.com/cosmos/cosmos-sdk/blob/v0.52.0-beta.1/x/auth/tx/encoder.go ``` See [ADR-020](../../architecture/adr-020-protobuf-transaction-encoding.md) for details of how a transaction is encoded. @@ -245,39 +245,3 @@ Protobuf types can be defined to encode: We encourage developers to follow industry guidelines: [Protocol Buffers style guide](https://developers.google.com/protocol-buffers/docs/style) and [Buf](https://buf.build/docs/style-guide), see more details in [ADR 023](../../architecture/adr-023-protobuf-naming.md) - -### How to update modules to protobuf encoding - -If modules do not contain any interfaces (e.g. `Account` or `Content`), then they -may simply migrate any existing types that -are encoded and persisted via their concrete Amino codec to Protobuf (see 1. for further guidelines) and accept a `Marshaler` as the codec which is implemented via the `ProtoCodec` -without any further customization. - -However, if a module type composes an interface, it must wrap it in the `sdk.Any` (from `/types` package) type. To do that, a module-level .proto file must use [`google.protobuf.Any`](https://github.com/protocolbuffers/protobuf/blob/master/src/google/protobuf/any.proto) for respective message type interface types. - -For example, in the `x/evidence` module defines an `Evidence` interface, which is used by the `MsgSubmitEvidence`. The structure definition must use `sdk.Any` to wrap the evidence file. In the proto file we define it as follows: - -```protobuf -// proto/cosmos/evidence/v1beta1/tx.proto - -message MsgSubmitEvidence { - string submitter = 1; - google.protobuf.Any evidence = 2 [(cosmos_proto.accepts_interface) = "cosmos.evidence.v1beta1.Evidence"]; -} -``` - -The Cosmos SDK `codec.Codec` interface provides support methods `MarshalInterface` and `UnmarshalInterface` to easy encoding of state to `Any`. - -Module should register interfaces using `InterfaceRegistry` which provides a mechanism for registering interfaces: `RegisterInterface(protoName string, iface interface{}, impls ...proto.Message)` and implementations: `RegisterImplementations(iface interface{}, impls ...proto.Message)` that can be safely unpacked from Any, similarly to type registration with Amino: - -```go reference -https://github.com/cosmos/cosmos-sdk/blob/v0.50.0-alpha.0/codec/types/interface_registry.go#L28-L75 -``` - -In addition, an `UnpackInterfaces` phase should be introduced to deserialization to unpack interfaces before they're needed. Protobuf types that contain a protobuf `Any` either directly or via one of their members should implement the `UnpackInterfacesMessage` interface: - -```go -type UnpackInterfacesMessage interface { - UnpackInterfaces(InterfaceUnpacker) error -} -``` diff --git a/docs/learn/advanced/09-telemetry.md b/docs/learn/advanced/09-telemetry.md index c5916544f111..9690d9b590ea 100644 --- a/docs/learn/advanced/09-telemetry.md +++ b/docs/learn/advanced/09-telemetry.md @@ -13,17 +13,18 @@ their application through the use of the `telemetry` package. To enable telemetr The Cosmos SDK currently supports enabling in-memory and prometheus as telemetry sinks. In-memory sink is always attached (when the telemetry is enabled) with 10 second interval and 1 minute retention. This means that metrics will be aggregated over 10 seconds, and metrics will be kept alive for 1 minute. -To query active metrics (see retention note above) you have to enable API server (`api.enabled = true` in the app.toml). Single API endpoint is exposed: `http://localhost:1317/metrics?format={text|prometheus}`, the default being `text`. +To query active metrics (see retention note above) you have to enable API server (`api.enabled = true` in the app.toml). Single API endpoint is exposed: `http://localhost:1317/metrics?format={text|prometheus}` (or port `1318` in v2) , the default being `text`. ## Emitting metrics If telemetry is enabled via configuration, a single global metrics collector is registered via the [go-metrics](https://github.com/hashicorp/go-metrics) library. This allows emitting and collecting -metrics through simple [API](https://github.com/cosmos/cosmos-sdk/blob/v0.50.0-alpha.0/telemetry/wrapper.go). Example: +metrics through simple [API](https://github.com/cosmos/cosmos-sdk/blob/v0.50.10/telemetry/wrapper.go). Example: ```go func EndBlocker(ctx sdk.Context, k keeper.Keeper) { - defer telemetry.ModuleMeasureSince(types.ModuleName, time.Now(), telemetry.MetricKeyEndBlocker) + start := telemetry.Now() + defer telemetry.ModuleMeasureSince(types.ModuleName, start, telemetry.MetricKeyEndBlocker) // ... } @@ -69,60 +70,32 @@ Consider the following examples with enough granularity and adequate cardinality * begin/end blocker time * tx gas used * block gas used -* amount of tokens minted -* amount of accounts created The following examples expose too much cardinality and may not even prove to be useful: * transfers between accounts with amount * voting/deposit amount from unique addresses +## Idempotency + +Metrics aren't idempotent, so if a metric is emitted twice, it will be counted twice. +This is important to keep in mind when collecting metrics. If a module is called twice, the metrics will be emitted twice (for instance in `CheckTx`, `SimulateTx` or `DeliverTx`). + ## Supported Metrics -| Metric | Description | Unit | Type | -|:--------------------------------|:------------------------------------------------------------------------------------------|:----------------|:--------| -| `tx_count` | Total number of txs processed via `DeliverTx` | tx | counter | -| `tx_successful` | Total number of successful txs processed via `DeliverTx` | tx | counter | -| `tx_failed` | Total number of failed txs processed via `DeliverTx` | tx | counter | -| `tx_gas_used` | The total amount of gas used by a tx | gas | gauge | -| `tx_gas_wanted` | The total amount of gas requested by a tx | gas | gauge | -| `tx_msg_send` | The total amount of tokens sent in a `MsgSend` (per denom) | token | gauge | -| `tx_msg_withdraw_reward` | The total amount of tokens withdrawn in a `MsgWithdrawDelegatorReward` (per denom) | token | gauge | -| `tx_msg_withdraw_commission` | The total amount of tokens withdrawn in a `MsgWithdrawValidatorCommission` (per denom) | token | gauge | -| `tx_msg_delegate` | The total amount of tokens delegated in a `MsgDelegate` | token | gauge | -| `tx_msg_begin_unbonding` | The total amount of tokens undelegated in a `MsgUndelegate` | token | gauge | -| `tx_msg_begin_begin_redelegate` | The total amount of tokens redelegated in a `MsgBeginRedelegate` | token | gauge | -| `tx_msg_ibc_transfer` | The total amount of tokens transferred via IBC in a `MsgTransfer` (source or sink chain) | token | gauge | -| `ibc_transfer_packet_receive` | The total amount of tokens received in a `FungibleTokenPacketData` (source or sink chain) | token | gauge | -| `new_account` | Total number of new accounts created | account | counter | -| `gov_proposal` | Total number of governance proposals | proposal | counter | -| `gov_vote` | Total number of governance votes for a proposal | vote | counter | -| `gov_deposit` | Total number of governance deposits for a proposal | deposit | counter | -| `staking_delegate` | Total number of delegations | delegation | counter | -| `staking_undelegate` | Total number of undelegations | undelegation | counter | -| `staking_redelegate` | Total number of redelegations | redelegation | counter | -| `ibc_transfer_send` | Total number of IBC transfers sent from a chain (source or sink) | transfer | counter | -| `ibc_transfer_receive` | Total number of IBC transfers received to a chain (source or sink) | transfer | counter | -| `ibc_client_create` | Total number of clients created | create | counter | -| `ibc_client_update` | Total number of client updates | update | counter | -| `ibc_client_upgrade` | Total number of client upgrades | upgrade | counter | -| `ibc_client_misbehaviour` | Total number of client misbehaviours | misbehaviour | counter | -| `ibc_connection_open-init` | Total number of connection `OpenInit` handshakes | handshake | counter | -| `ibc_connection_open-try` | Total number of connection `OpenTry` handshakes | handshake | counter | -| `ibc_connection_open-ack` | Total number of connection `OpenAck` handshakes | handshake | counter | -| `ibc_connection_open-confirm` | Total number of connection `OpenConfirm` handshakes | handshake | counter | -| `ibc_channel_open-init` | Total number of channel `OpenInit` handshakes | handshake | counter | -| `ibc_channel_open-try` | Total number of channel `OpenTry` handshakes | handshake | counter | -| `ibc_channel_open-ack` | Total number of channel `OpenAck` handshakes | handshake | counter | -| `ibc_channel_open-confirm` | Total number of channel `OpenConfirm` handshakes | handshake | counter | -| `ibc_channel_close-init` | Total number of channel `CloseInit` handshakes | handshake | counter | -| `ibc_channel_close-confirm` | Total number of channel `CloseConfirm` handshakes | handshake | counter | -| `tx_msg_ibc_recv_packet` | Total number of IBC packets received | packet | counter | -| `tx_msg_ibc_acknowledge_packet` | Total number of IBC packets acknowledged | acknowledgement | counter | -| `ibc_timeout_packet` | Total number of IBC timeout packets | timeout | counter | -| `store_iavl_get` | Duration of an IAVL `Store#Get` call | ms | summary | -| `store_iavl_set` | Duration of an IAVL `Store#Set` call | ms | summary | -| `store_iavl_has` | Duration of an IAVL `Store#Has` call | ms | summary | -| `store_iavl_delete` | Duration of an IAVL `Store#Delete` call | ms | summary | -| `store_iavl_commit` | Duration of an IAVL `Store#Commit` call | ms | summary | -| `store_iavl_query` | Duration of an IAVL `Store#Query` call | ms | summary | +| Metric | Description | Unit | Type | +| ------------------- | ------------------------------------------------------------------------------ | ---- | ------- | +| `tx_count` | Total number of txs processed via `DeliverTx` | tx | counter | +| `tx_successful` | Total number of successful txs processed via `DeliverTx` | tx | counter | +| `tx_failed` | Total number of failed txs processed via `DeliverTx` | tx | counter | +| `tx_gas_used` | The total amount of gas used by a tx | gas | gauge | +| `tx_gas_wanted` | The total amount of gas requested by a tx | gas | gauge | +| `store_iavl_get` | Duration of an IAVL `Store#Get` call | ms | summary | +| `store_iavl_set` | Duration of an IAVL `Store#Set` call | ms | summary | +| `store_iavl_has` | Duration of an IAVL `Store#Has` call | ms | summary | +| `store_iavl_delete` | Duration of an IAVL `Store#Delete` call | ms | summary | +| `store_iavl_commit` | Duration of an IAVL `Store#Commit` call | ms | summary | +| `store_iavl_query` | Duration of an IAVL `Store#Query` call | ms | summary | +| `begin_blocker` | Duration of the `BeginBlock` call per module | ms | summary | +| `end_blocker` | Duration of the `EndBlock` call per module | ms | summary | +| `server_info` | Information about the server, such as version, commit, and build date, upgrade | - | gauge | diff --git a/docs/learn/advanced/12-simulation.md b/docs/learn/advanced/12-simulation.md index dfbcddd0d29f..c30d398c32e9 100644 --- a/docs/learn/advanced/12-simulation.md +++ b/docs/learn/advanced/12-simulation.md @@ -7,37 +7,26 @@ sidebar_position: 1 The Cosmos SDK offers a full fledged simulation framework to fuzz test every message defined by a module. -On the Cosmos SDK, this functionality is provided by [`SimApp`](https://github.com/cosmos/cosmos-sdk/blob/v0.50.0-alpha.0/simapp/app_v2.go), which is a -`Baseapp` application that is used for running the [`simulation`](https://github.com/cosmos/cosmos-sdk/blob/v0.50.0-alpha.0/x/simulation) module. -This module defines all the simulation logic as well as the operations for -randomized parameters like accounts, balances etc. +On the Cosmos SDK, this functionality is provided by [`SimApp`](https://github.com/cosmos/cosmos-sdk/blob/v0.50.0-alpha.0/simapp/app_v2.go), which is a `Baseapp` application that is used for running the [`simulation`](https://github.com/cosmos/cosmos-sdk/blob/23cf89cce1882ba9c8280e64735ae200504bfdce/simsx/README.md#L1) package. This package defines all the simulation logic as well as the operations for randomized parameters like accounts, balances etc. ## Goals -The blockchain simulator tests how the blockchain application would behave under -real life circumstances by generating and sending randomized messages. -The goal of this is to detect and debug failures that could halt a live chain, -by providing logs and statistics about the operations run by the simulator as -well as exporting the latest application state when a failure was found. +The blockchain simulator tests how the blockchain application would behave under real life circumstances by generating and sending randomized messages. The goal of this is to detect and debug failures that could halt a live chain, by providing logs and statistics about the operations run by the simulator as well as exporting the latest application state when a failure was found. -Its main difference with integration testing is that the simulator app allows -you to pass parameters to customize the chain that's being simulated. -This comes in handy when trying to reproduce bugs that were generated in the -provided operations (randomized or not). +Its main difference with integration testing is that the simulator app allows you to pass parameters to customize the chain that's being simulated. This comes in handy when trying to reproduce bugs that were generated in the provided operations (randomized or not). ## Simulation commands The simulation app has different commands, each of which tests a different failure type: -* `AppImportExport`: The simulator exports the initial app state and then it - creates a new app with the exported `genesis.json` as an input, checking for - inconsistencies between the stores. +* `AppImportExport`: The simulator exports the initial app state and then it creates a new app with the exported `genesis.json` as an input, checking for inconsistencies between the stores. * `AppSimulationAfterImport`: Queues two simulations together. The first one provides the app state (_i.e_ genesis) to the second. Useful to test software upgrades or hard-forks from a live chain. * `AppStateDeterminism`: Checks that all the nodes return the same values, in the same order. -* `BenchmarkInvariants`: Analysis of the performance of running all modules' invariants (_i.e_ sequentially runs a [benchmark](https://pkg.go.dev/testing/#hdr-Benchmarks) test). An invariant checks for - differences between the values that are on the store and the passive tracker. Eg: total coins held by accounts vs total supply tracker. +* `BenchmarkInvariants`: Analysis of the performance of running all modules' invariants (_i.e_ sequentially runs a [benchmark](https://pkg.go.dev/testing/#hdr-Benchmarks) test). An invariant checks for differences between the values that are on the store and the passive tracker. Eg: total coins held by accounts vs total supply tracker. * `FullAppSimulation`: General simulation mode. Runs the chain and the specified operations for a given number of blocks. Tests that there're no `panics` on the simulation. It does also run invariant checks on every `Period` but they are not benchmarked. +* `FuzzFullAppSimulation`: Runs general simulation mode with the [go fuzzer](https://go.dev/doc/security/fuzz/) to find panics. +* `AppStateDeterminism`: Runs a few seeds many times to test that the apphash is deterministic across the runs. Each simulation must receive a set of inputs (_i.e_ flags) such as the number of blocks that the simulation is run, seed, block size, etc. @@ -47,23 +36,18 @@ Check the full list of flags [here](https://github.com/cosmos/cosmos-sdk/blob/v0 In addition to the various inputs and commands, the simulator runs in three modes: -1. Completely random where the initial state, module parameters and simulation - parameters are **pseudo-randomly generated**. -2. From a `genesis.json` file where the initial state and the module parameters are defined. - This mode is helpful for running simulations on a known state such as a live network export where a new (mostly likely breaking) version of the application needs to be tested. -3. From a `params.json` file where the initial state is pseudo-randomly generated but the module and simulation parameters can be provided manually. - This allows for a more controlled and deterministic simulation setup while allowing the state space to still be pseudo-randomly simulated. - The list of available parameters are listed [here](https://github.com/cosmos/cosmos-sdk/blob/v0.50.0-alpha.0/x/simulation/client/cli/flags.go#L59-L78). +1. Completely random where the initial state, module parameters and simulation parameters are **pseudo-randomly generated**. +2. From a `genesis.json` file where the initial state and the module parameters are defined. This mode is helpful for running simulations on a known state such as a live network export where a new (mostly likely breaking) version of the application needs to be tested. +3. From a `params.json` file where the initial state is pseudo-randomly generated but the module and simulation parameters can be provided manually. This allows for a more controlled and deterministic simulation setup while allowing the state space to still be pseudo-randomly simulated. All available parameters are listed [here](https://github.com/cosmos/cosmos-sdk/blob/v0.50.0-alpha.0/x/simulation/client/cli/flags.go#L59-L78). :::tip -These modes are not mutually exclusive. So you can for example run a randomly -generated genesis state (`1`) with manually generated simulation params (`3`). +These modes are not mutually exclusive. So you can for example run a randomly generated genesis state (`1`) with manually generated simulation params (`3`). ::: ## Usage This is a general example of how simulations are run. For more specific examples -check the Cosmos SDK [Makefile](https://github.com/cosmos/cosmos-sdk/blob/v0.50.0-alpha.0/Makefile#L282-L318). +check the Cosmos SDK [Makefile](https://github.com/cosmos/cosmos-sdk/blob/23cf89cce1882ba9c8280e64735ae200504bfdce/scripts/build/simulations.mk#L1-L104). ```bash $ go test -mod=readonly github.com/cosmos/cosmos-sdk/simapp \ diff --git a/docs/learn/beginner/00-app-anatomy.md b/docs/learn/beginner/00-app-anatomy.md index ae5a20062053..9757e7e95af3 100644 --- a/docs/learn/beginner/00-app-anatomy.md +++ b/docs/learn/beginner/00-app-anatomy.md @@ -275,7 +275,7 @@ https://github.com/cosmos/gaia/blob/26ae7c2/cmd/gaiad/cmd/root.go#L39-L80 ## Dependencies and Makefile -This section is optional, as developers are free to choose their dependency manager and project building method. That said, the current most used framework for versioning control is [`go.mod`](https://github.com/golang/go/wiki/Modules). It ensures each of the libraries used throughout the application are imported with the correct version. +This section is optional, as developers are free to choose their dependency manager and project building method. That said, the current most used framework for versioning control is [`go.mod`](https://go.dev/wiki/Modules). It ensures each of the libraries used throughout the application are imported with the correct version. The following is the `go.mod` of the [Cosmos Hub](https://github.com/cosmos/gaia), provided as an example. diff --git a/docs/learn/intro/00-overview.md b/docs/learn/intro/00-overview.md index bb32d84a962f..7b0a3da037b5 100644 --- a/docs/learn/intro/00-overview.md +++ b/docs/learn/intro/00-overview.md @@ -9,13 +9,13 @@ sidebar_position: 1 The [Cosmos SDK](https://github.com/cosmos/cosmos-sdk) is an open-source toolkit for building multi-asset public Proof-of-Stake (PoS) blockchains, like the Cosmos Hub, as well as permissioned Proof-of-Authority (PoA) blockchains. Blockchains built with the Cosmos SDK are generally referred to as **application-specific blockchains**. The goal of the Cosmos SDK is to allow developers to easily create custom blockchains from scratch that can natively interoperate with other blockchains. -We further this modular approach by allowing developers to plug and play with different consensus engines this can range from the [CometBFT](https://github.com/cometbft/cometbft) or [Rollkit](https://rollkit.dev/). +We further this modular approach by allowing developers to plug and play with different consensus engines this can range from [CometBFT](https://cometbft.com/) or [Rollkit](https://rollkit.dev/). SDK-based blockchains have the choice to use the predefined modules or to build their own modules. What this means is that developers can build a blockchain that is tailored to their specific use case, without having to worry about the low-level details of building a blockchain from scratch. Predefined modules include staking, governance, and token issuance, among others. What's more, the Cosmos SDK is a capabilities-based system that allows developers to better reason about the security of interactions between modules. For a deeper look at capabilities, jump to [Object-Capability Model](../advanced/10-ocap.md). -How you can look at this is if we imagine that the SDK is like a lego kit. You can choose to build the basic house from the instructions or you can choose to modify your house and add more floors, more doors, more windows. The choice is yours. +You can think of the SDK as a lego kit. You can choose to build the basic house from the instructions, or you can choose to modify your house and add more floors, more doors, more windows. The choice is yours. ## What are Application-Specific Blockchains @@ -27,17 +27,17 @@ Learn more about [application-specific blockchains](./01-why-app-specific.md). ## What is Modularity -Today there is a lot of talk around modularity and discussions between monolithic and modular. Originally the Cosmos SDK was built with a vision of modularity in mind. Modularity is derived from splitting a blockchain into customizable layers of execution, consensus, settlement and data availability, which is what the Cosmos SDK enables. This means that developers can plug and play, making their blockchain customisable by using different software for different layers. For example you can choose to build a vanilla chain and use the Cosmos SDK with CometBFT. CometBFT will be your consensus layer and the chain itself would be the settlement and execution layer. Another route could be to use the SDK with Rollkit and Celestia as your consensus and data availability layer. The benefit of modularity is that you can customize your chain to your specific use case. +Today, there is a lot of talk around modularity and discussions between monolithic and modular. Originally, the Cosmos SDK was built with a vision of modularity in mind. Modularity is derived from splitting a blockchain into customizable layers of execution, consensus, settlement and data availability, which is what the Cosmos SDK enables. This means that developers can plug and play, making their blockchain customizable by using different software for different layers. For example, you can choose to build a vanilla chain and use the Cosmos SDK with CometBFT. CometBFT will be your consensus layer and the chain itself would be the settlement and execution layer. Another route could be to use the SDK with Rollkit and [Celestia](https://celestia.org/) as your consensus and data availability layer. The benefit of modularity is that you can customize your chain to your specific use case. ## Why the Cosmos SDK The Cosmos SDK is the most advanced framework for building custom modular application-specific blockchains today. Here are a few reasons why you might want to consider building your decentralized application with the Cosmos SDK: -* It allows you to plug and play and customize your consensus layer. As above you can use Rollkit and Celestia as your consensus and data availability layer. This offers a lot of flexibility and customisation. -* Previously the default consensus engine available within the Cosmos SDK is [CometBFT](https://github.com/cometbft/cometbft). CometBFT is the most (and only) mature BFT consensus engine in existence. It is widely used across the industry and is considered the gold standard consensus engine for building Proof-of-Stake systems. +* It allows you to plug and play and customize your consensus layer. As mentioned above, you can use Rollkit and Celestia as your consensus and data availability layer. This offers a lot of flexibility and customization. +* Previously the default consensus engine available within the Cosmos SDK is [CometBFT](https://cometbft.com/). CometBFT is the most (and only) mature BFT consensus engine in existence. It is widely used across the industry and is considered the gold standard consensus engine for building Proof-of-Stake systems. * The Cosmos SDK is open-source and designed to make it easy to build blockchains out of composable [modules](../../build/modules). As the ecosystem of open-source Cosmos SDK modules grows, it will become increasingly easier to build complex decentralized platforms with it. * The Cosmos SDK is inspired by capabilities-based security, and informed by years of wrestling with blockchain state-machines. This makes the Cosmos SDK a very secure environment to build blockchains. -* Most importantly, the Cosmos SDK has already been used to build many application-specific blockchains that are already in production. Among others, we can cite [Cosmos Hub](https://hub.cosmos.network), [IRIS Hub](https://irisnet.org), [Binance Chain](https://docs.binance.org/), [Terra](https://terra.money/) or [Kava](https://www.kava.io/). [Many more](https://cosmos.network/ecosystem) are building on the Cosmos SDK. +* Most importantly, the Cosmos SDK has already been used to build many application-specific blockchains that are already in production. Among others, we can cite [Cosmos Hub](https://hub.cosmos.network), [Osmosis](https://osmosis.zone/), [Binance Chain](https://docs.binance.org/), [Terra](https://terra.money/) or [Dydx](https://dydx.exchange/). [Many more](https://cosmos.network/ecosystem) are building on the Cosmos SDK. ## Getting started with the Cosmos SDK diff --git a/docs/learn/intro/02-sdk-app-architecture.md b/docs/learn/intro/02-sdk-app-architecture.md index 6ace65e57abc..1f6d9df78d2d 100644 --- a/docs/learn/intro/02-sdk-app-architecture.md +++ b/docs/learn/intro/02-sdk-app-architecture.md @@ -54,7 +54,7 @@ flowchart LR A -->|"For each T in B: apply(T)"| B ``` -In a blockchain context, the state machine is deterministic. This means that if a node is started at a given state and replays the same sequence of transactions, it will always end up with the same final state. +In a blockchain context, the state machine is [deterministic](https://en.wikipedia.org/wiki/Deterministic_system). This means that if a node is started at a given state and replays the same sequence of transactions, it will always end up with the same final state. The Cosmos SDK gives developers maximum flexibility to define the state of their application, transaction types and state transition functions. The process of building state machines with the Cosmos SDK will be described more in-depth in the following sections. But first, let us see how the state machine is replicated using various consensus engines, such as CometBFT. @@ -117,7 +117,7 @@ Note that **CometBFT only handles transaction bytes**. It has no knowledge of wh Here are the most important messages of the ABCI: -* `CheckTx`: When a transaction is received by CometBFT, it is passed to the application to check if a few basic requirements are met. `CheckTx` is used to protect the mempool of full-nodes against spam transactions. . A special handler called the [`AnteHandler`](../beginner/04-gas-fees.md#antehandler) is used to execute a series of validation steps such as checking for sufficient fees and validating the signatures. If the checks are valid, the transaction is added to the [mempool](https://docs.cometbft.com/v1.0/explanation/core/mempool) and relayed to peer nodes. Note that transactions are not processed (i.e. no modification of the state occurs) with `CheckTx` since they have not been included in a block yet. +* `CheckTx`: When a transaction is received by CometBFT, it is passed to the application to check if a few basic requirements are met. `CheckTx` is used to protect the mempool of full-nodes against spam transactions. A special handler called the [`AnteHandler`](../beginner/04-gas-fees.md#antehandler) is used to execute a series of validation steps such as checking for sufficient fees and validating the signatures. If the checks are valid, the transaction is added to the [mempool](https://docs.cometbft.com/v1.0/explanation/core/mempool) and relayed to peer nodes. Note that transactions are not processed (i.e. no modification of the state occurs) with `CheckTx` since they have not been included in a block yet. * `DeliverTx`: When a [valid block](https://docs.cometbft.com/v1.0/spec/core/data_structures#block) is received by CometBFT, each transaction in the block is passed to the application via `DeliverTx` in order to be processed. It is during this stage that the state transitions occur. The `AnteHandler` executes again, along with the actual [`Msg` service](../../build/building-modules/03-msg-services.md) RPC for each message in the transaction. * `BeginBlock`/`EndBlock`: These messages are executed at the beginning and the end of each block, whether the block contains transactions or not. It is useful to trigger automatic execution of logic. Proceed with caution though, as computationally expensive loops could slow down your blockchain, or even freeze it if the loop is infinite. @@ -136,4 +136,4 @@ If we use the example of Rollkit, a user initiates a transaction, which is then The Interoperability Layer enables communication and interaction between different blockchains. This layer facilitates cross-chain transactions and data sharing, allowing various blockchain networks to interoperate seamlessly. Interoperability is key for building a connected ecosystem of blockchains, enhancing their functionality and reach. -In this case we have separated the layers even further to really illustrate the components that make-up the blockchain architecture and it is important to note that the Cosmos SDK is designed to be interoperable with other blockchains. This is achieved through the use of the Inter-Blockchain Communication (IBC) protocol, which allows different blockchains to communicate and transfer assets between each other. +In this case we have separated the layers even further to really illustrate the components that make-up the blockchain architecture and it is important to note that the Cosmos SDK is designed to be interoperable with other blockchains. This is achieved through the use of the [Inter-Blockchain Communication (IBC) protocol](https://www.ibcprotocol.dev/), which allows different blockchains to communicate and transfer assets between each other. diff --git a/docs/learn/intro/03-sdk-design.md b/docs/learn/intro/03-sdk-design.md index e2edcd4efb02..9ae17b73bb16 100644 --- a/docs/learn/intro/03-sdk-design.md +++ b/docs/learn/intro/03-sdk-design.md @@ -22,7 +22,7 @@ Here is a simplified view of how transactions are handled by an application buil Here is an example of this from `simapp`, the Cosmos SDK demonstration app: ```go reference -https://github.com/cosmos/cosmos-sdk/blob/v0.50.0-alpha.0/simapp/app.go#L170-L212 +https://github.com/cosmos/cosmos-sdk/blob/v0.52.0-beta.1/simapp/app.go#L145-L186 ``` The goal of `baseapp` is to provide a secure interface between the store and the extensible state machine while defining as little about the state machine as possible (staying true to the ABCI). @@ -33,7 +33,7 @@ For more on `baseapp`, please click [here](../advanced/00-baseapp.md). The Cosmos SDK provides a [`multistore`](../advanced/04-store.md#multistore) for persisting state. The multistore allows developers to declare any number of [`KVStores`](../advanced/04-store.md#base-layer-kvstores). These `KVStores` only accept the `[]byte` type as value and therefore any custom structure needs to be marshalled using [a codec](../advanced/05-encoding.md) before being stored. -The multistore abstraction is used to divide the state in distinct compartments, each managed by its own module. For more on the multistore, click [here](../advanced/04-store.md#multistore) +The multistore abstraction is used to divide the state in distinct compartments, each managed by its own module. For more on the multistore, click [here](../advanced/04-store.md#multistore). ## Modules @@ -61,6 +61,6 @@ Cosmos SDK modules are defined in the `x/` folder of the Cosmos SDK. Some core m * `x/auth`: Used to manage accounts and signatures. * `x/bank`: Used to enable tokens and token transfers. -* `x/staking` + `x/slashing`: Used to build Proof-Of-Stake blockchains. +* `x/staking` + `x/slashing`: Used to build Proof-of-Stake blockchains. -In addition to the already existing modules in `x/`, that anyone can use in their app, the Cosmos SDK lets you build your own custom modules. You can check an [example of that in the tutorial](https://tutorials.cosmos.network/). +In addition to the already existing modules in `x/`, which anyone can use in their app, the Cosmos SDK lets you build your own custom modules. You can check an [example of that in the tutorial](https://tutorials.cosmos.network/). diff --git a/docs/learn/learn.md b/docs/learn/learn.md index b8f64821a906..3414fa1a2039 100644 --- a/docs/learn/learn.md +++ b/docs/learn/learn.md @@ -3,8 +3,8 @@ sidebar_position: 0 --- # Learn -* [Introduction](./intro/00-overview.md) - Dive into the fundamentals of Cosmos SDK with an insightful introduction, -laying the groundwork for understanding blockchain development. In this section we provide a High-Level Overview of the SDK, then dive deeper into Core concepts such as Application-Specific Blockchains, Blockchain Architecture, and finally we begin to explore what are the main components of the SDK. +* [Introduction](./intro/00-overview.md) - Dive into the fundamentals of Cosmos SDK with an insightful introduction, +laying the groundwork for understanding blockchain development. In this section, we provide a High-Level Overview of the SDK, then dive deeper into Core concepts such as Application-Specific Blockchains, Blockchain Architecture, and finally, we begin to explore the main components of the SDK. * [Beginner](./beginner/00-app-anatomy.md) - Start your journey with beginner-friendly resources in the Cosmos SDK's "Learn" section, providing a gentle entry point for newcomers to blockchain development. Here we focus on a little more detail, covering the Anatomy of a Cosmos SDK Application, Transaction Lifecycles, Accounts and lastly, Gas and Fees. * [Advanced](./advanced/00-baseapp.md) - Level up your Cosmos SDK expertise with advanced topics, tailored for experienced diff --git a/docs/rfc/rfc-006-handlers.md b/docs/rfc/rfc-006-handlers.md index a22992ccdb0c..9770c6774d90 100644 --- a/docs/rfc/rfc-006-handlers.md +++ b/docs/rfc/rfc-006-handlers.md @@ -24,7 +24,7 @@ This has led us to look at a design which would allow the usage of TinyGo and other technologies. We looked at TinyGo for our first target in order to compile down to a 32 bit environment which could be used with -things like [Risc-0](https://www.risczero.com/), [Fluent](https://fluentlabs.xyz/) and other technologies. When speaking with the teams behind these technologies +things like [Risc-0](https://www.risczero.com/), [Fluent](https://fluent.xyz/) and other technologies. When speaking with the teams behind these technologies we found that they were interested in using the Cosmos SDK but were unable to due to being unable to use TinyGo or the Cosmos SDK go code in a 32 bit environment. diff --git a/errors/abci_test.go b/errors/abci_test.go index ca283997ae91..54afb8872600 100644 --- a/errors/abci_test.go +++ b/errors/abci_test.go @@ -102,7 +102,7 @@ func TestABCIInfoSerializeErr(t *testing.T) { }, } for msg, spec := range specs { - spec := spec + _, _, log := ABCIInfo(spec.src, spec.debug) if log != spec.exp { t.Errorf("%s: expected log %s, got %s", msg, spec.exp, log) diff --git a/fuzz/fuzz.patch b/fuzz/fuzz.patch new file mode 100644 index 000000000000..995b0d5b53e5 --- /dev/null +++ b/fuzz/fuzz.patch @@ -0,0 +1,81 @@ +diff --git a/types/address_test.go b/types/address_test.go +index 014a48b73..99f9a1a86 100644 +--- a/types/address_test.go ++++ b/types/address_test.go +@@ -26,10 +26,6 @@ type addressTestSuite struct { + suite.Suite + } + +-func TestAddressTestSuite(t *testing.T) { +- suite.Run(t, new(addressTestSuite)) +-} +- + func (s *addressTestSuite) SetupSuite() { + s.T().Parallel() + } +@@ -403,65 +399,6 @@ func (s *addressTestSuite) TestAddressInterface() { + } + } + +-func (s *addressTestSuite) TestBech32ifyAddressBytes() { +- type args struct { +- prefix string +- bs []byte +- } +- tests := []struct { +- name string +- args args +- want string +- wantErr bool +- }{ +- {"empty address", args{"prefixa", []byte{}}, "", false}, +- {"empty prefix", args{"", addr20byte}, "", true}, +- {"10-byte address", args{"prefixa", addr10byte}, "prefixa1qqqsyqcyq5rqwzqf3953cc", false}, +- {"10-byte address", args{"prefixb", addr10byte}, "prefixb1qqqsyqcyq5rqwzqf20xxpc", false}, +- {"20-byte address", args{"prefixa", addr20byte}, "prefixa1qqqsyqcyq5rqwzqfpg9scrgwpugpzysn7hzdtn", false}, +- {"20-byte address", args{"prefixb", addr20byte}, "prefixb1qqqsyqcyq5rqwzqfpg9scrgwpugpzysnrujsuw", false}, +- } +- for _, tt := range tests { +- s.T().Run(tt.name, func(t *testing.T) { +- got, err := types.Bech32ifyAddressBytes(tt.args.prefix, tt.args.bs) +- if (err != nil) != tt.wantErr { +- t.Errorf("Bech32ifyBytes() error = %v, wantErr %v", err, tt.wantErr) +- return +- } +- require.Equal(t, tt.want, got) +- }) +- } +-} +- +-func (s *addressTestSuite) TestMustBech32ifyAddressBytes() { +- type args struct { +- prefix string +- bs []byte +- } +- tests := []struct { +- name string +- args args +- want string +- wantPanic bool +- }{ +- {"empty address", args{"prefixa", []byte{}}, "", false}, +- {"empty prefix", args{"", addr20byte}, "", true}, +- {"10-byte address", args{"prefixa", addr10byte}, "prefixa1qqqsyqcyq5rqwzqf3953cc", false}, +- {"10-byte address", args{"prefixb", addr10byte}, "prefixb1qqqsyqcyq5rqwzqf20xxpc", false}, +- {"20-byte address", args{"prefixa", addr20byte}, "prefixa1qqqsyqcyq5rqwzqfpg9scrgwpugpzysn7hzdtn", false}, +- {"20-byte address", args{"prefixb", addr20byte}, "prefixb1qqqsyqcyq5rqwzqfpg9scrgwpugpzysnrujsuw", false}, +- } +- for _, tt := range tests { +- s.T().Run(tt.name, func(t *testing.T) { +- if tt.wantPanic { +- require.Panics(t, func() { types.MustBech32ifyAddressBytes(tt.args.prefix, tt.args.bs) }) +- return +- } +- require.Equal(t, tt.want, types.MustBech32ifyAddressBytes(tt.args.prefix, tt.args.bs)) +- }) +- } +-} +- + func (s *addressTestSuite) TestAddressTypesEquals() { + addr1 := secp256k1.GenPrivKey().PubKey().Address() + accAddr1 := types.AccAddress(addr1) diff --git a/fuzz/oss-fuzz-build.sh b/fuzz/oss-fuzz-build.sh index faa7c76b5d7b..c829194dc2e4 100644 --- a/fuzz/oss-fuzz-build.sh +++ b/fuzz/oss-fuzz-build.sh @@ -1,5 +1,34 @@ #!/bin/bash +set -o nounset +set -o pipefail +set -o errexit +set -x + +cd $SRC +wget https://go.dev/dl/go1.23.1.linux-amd64.tar.gz +mkdir $SRC/new-go +rm -rf /root/.go && tar -C $SRC/new-go/ -xzf go1.23.1.linux-amd64.tar.gz +mv $SRC/new-go/go /root/.go +ls /root/.go + +cd $SRC/go-118-fuzz-build +go build . +mv go-118-fuzz-build /root/go/bin/ +cd $SRC/cosmos-sdk +git apply ./fuzz/fuzz.patch + +mkdir $SRC/cosmos-sdk/types/fuzzing +mv $SRC/cosmos-sdk/types/address*_test.go $SRC/cosmos-sdk/types/fuzzing/ +sed 's/package types_test/package fuzzing/g' -i "$SRC"/cosmos-sdk/types/fuzzing/* + +rm $SRC/cosmos-sdk/math/dec_internal_test.go +rm $SRC/cosmos-sdk/math/int_internal_test.go +rm $SRC/cosmos-sdk/math/uint_internal_test.go +mv $SRC/cosmos-sdk/types/fuzz_test.go $SRC/cosmos-sdk/types/fuzz.go +rm $SRC/cosmos-sdk/types/*_test.go +mv $SRC/cosmos-sdk/types/fuzz.go $SRC/cosmos-sdk/types/fuzz_test.go + set -euo pipefail export FUZZ_ROOT="github.com/cosmos/cosmos-sdk" @@ -18,25 +47,22 @@ build_go_fuzzer() { compile_native_go_fuzzer cosmossdk.io/math FuzzLegacyNewDecFromStr fuzz_math_legacy_new_dec_from_str ) -go get github.com/AdamKorcz/go-118-fuzz-build/testing +printf "package types \nimport _ \"github.com/AdamKorcz/go-118-fuzz-build/testing\"\n" > ./types/fuzz-register.go +go mod edit -replace github.com/AdamKorcz/go-118-fuzz-build=$SRC/go-118-fuzz-build +go mod tidy # TODO: fails to build with # main.413864645.go:12:2: found packages query (collections_pagination.go) and query_test (fuzz_test.go_fuzz.go) in /src/cosmos-sdk/types/query # because of the separate query_test package. # compile_native_go_fuzzer "$FUZZ_ROOT"/types/query FuzzPagination fuzz_types_query_pagination compile_native_go_fuzzer "$FUZZ_ROOT"/types FuzzCoinUnmarshalJSON fuzz_types_coin_unmarshal_json -compile_native_go_fuzzer "$FUZZ_ROOT"/types FuzzBech32AccAddrConsistencyYAML fuzz_types_bech32_acc_addr_consistency_yaml - +compile_native_go_fuzzer "$FUZZ_ROOT"/types/fuzzing FuzzBech32AccAddrConsistencyYAML fuzz_types_bech32_acc_addr_consistency_yaml build_go_fuzzer FuzzCryptoHDDerivePrivateKeyForPath fuzz_crypto_hd_deriveprivatekeyforpath build_go_fuzzer FuzzCryptoHDNewParamsFromPath fuzz_crypto_hd_newparamsfrompath - build_go_fuzzer FuzzCryptoTypesCompactbitarrayMarshalUnmarshal fuzz_crypto_types_compactbitarray_marshalunmarshal - build_go_fuzzer FuzzTendermintAminoDecodeTime fuzz_tendermint_amino_decodetime - build_go_fuzzer FuzzTypesParseCoin fuzz_types_parsecoin build_go_fuzzer FuzzTypesParseDecCoin fuzz_types_parsedeccoin build_go_fuzzer FuzzTypesParseTimeBytes fuzz_types_parsetimebytes build_go_fuzzer FuzzTypesDecSetString fuzz_types_dec_setstring - build_go_fuzzer FuzzUnknownProto fuzz_unknownproto diff --git a/go.mod b/go.mod index ab8bd9738c9e..316ed8448cf6 100644 --- a/go.mod +++ b/go.mod @@ -3,15 +3,15 @@ go 1.23.1 module github.com/cosmos/cosmos-sdk require ( - cosmossdk.io/api v0.7.5 + cosmossdk.io/api v0.7.6 cosmossdk.io/collections v0.4.0 - cosmossdk.io/core v1.0.0-alpha.2 - cosmossdk.io/core/testing v0.0.0-00010101000000-000000000000 + cosmossdk.io/core v1.0.0-alpha.4 + cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29 cosmossdk.io/depinject v1.0.0 cosmossdk.io/errors v1.0.1 cosmossdk.io/log v1.4.1 cosmossdk.io/math v1.3.0 - cosmossdk.io/schema v0.2.0 + cosmossdk.io/schema v0.3.1-0.20240930054013-7c6e0388a3f9 cosmossdk.io/store v1.1.1-0.20240418092142-896cdf1971bc cosmossdk.io/x/bank v0.0.0-20240226161501-23359a0b6d91 cosmossdk.io/x/staking v0.0.0-00010101000000-000000000000 @@ -39,13 +39,13 @@ require ( github.com/hashicorp/go-metrics v0.5.3 github.com/hashicorp/golang-lru v1.0.2 github.com/hdevalence/ed25519consensus v0.2.0 - github.com/huandu/skiplist v1.2.0 + github.com/huandu/skiplist v1.2.1 github.com/magiconair/properties v1.8.7 github.com/mattn/go-isatty v0.0.20 github.com/mdp/qrterminal/v3 v3.2.0 github.com/muesli/termenv v0.15.2 - github.com/prometheus/client_golang v1.20.3 - github.com/prometheus/common v0.59.1 + github.com/prometheus/client_golang v1.20.4 + github.com/prometheus/common v0.60.0 github.com/rs/zerolog v1.33.0 github.com/spf13/cast v1.7.0 github.com/spf13/cobra v1.8.1 @@ -56,8 +56,8 @@ require ( gitlab.com/yawning/secp256k1-voi v0.0.0-20230925100816-f2616030848b golang.org/x/crypto v0.27.0 golang.org/x/sync v0.8.0 - google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 - google.golang.org/grpc v1.66.2 + google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 + google.golang.org/grpc v1.67.1 google.golang.org/protobuf v1.34.2 gotest.tools/v3 v3.5.1 pgregory.net/rapid v1.1.0 @@ -168,7 +168,7 @@ require ( golang.org/x/text v0.18.0 // indirect golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect rsc.io/qr v0.2.0 // indirect @@ -184,7 +184,6 @@ require ( replace ( cosmossdk.io/api => ./api cosmossdk.io/collections => ./collections - cosmossdk.io/core/testing => ./core/testing cosmossdk.io/store => ./store cosmossdk.io/x/bank => ./x/bank cosmossdk.io/x/staking => ./x/staking diff --git a/go.sum b/go.sum index ca9079b0b3e4..5aff95150b03 100644 --- a/go.sum +++ b/go.sum @@ -4,8 +4,10 @@ buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.34.2-20240130113600-88e buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.34.2-20240130113600-88ef6483f90f.2/go.mod h1:HqcXMSa5qnNuakaMUo+hWhF51mKbcrZxGl9Vp5EeJXc= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cosmossdk.io/core v1.0.0-alpha.2 h1:epU0Xwces4Rgl5bMhHHkXGaGDcyucNGlC/JDH+Suckg= -cosmossdk.io/core v1.0.0-alpha.2/go.mod h1:abgLjeFLhtuKIYZWSPlVUgQBrKObO7ULV35KYfexE90= +cosmossdk.io/core v1.0.0-alpha.4 h1:9iuroT9ejDYETCsGkzkvs/wAY/5UFl7nCIINFRxyMJY= +cosmossdk.io/core v1.0.0-alpha.4/go.mod h1:3u9cWq1FAVtiiCrDPpo4LhR+9V6k/ycSG4/Y/tREWCY= +cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29 h1:NxxUo0GMJUbIuVg0R70e3cbn9eFTEuMr7ev1AFvypdY= +cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29/go.mod h1:8s2tPeJtSiQuoyPmr2Ag7meikonISO4Fv4MoO8+ORrs= cosmossdk.io/depinject v1.0.0 h1:dQaTu6+O6askNXO06+jyeUAnF2/ssKwrrszP9t5q050= cosmossdk.io/depinject v1.0.0/go.mod h1:zxK/h3HgHoA/eJVtiSsoaRaRA2D5U4cJ5thIG4ssbB8= cosmossdk.io/errors v1.0.1 h1:bzu+Kcr0kS/1DuPBtUFdWjzLqyUuCiyHjyJB6srBV/0= @@ -14,8 +16,8 @@ cosmossdk.io/log v1.4.1 h1:wKdjfDRbDyZRuWa8M+9nuvpVYxrEOwbD/CA8hvhU8QM= cosmossdk.io/log v1.4.1/go.mod h1:k08v0Pyq+gCP6phvdI6RCGhLf/r425UT6Rk/m+o74rU= cosmossdk.io/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE= cosmossdk.io/math v1.3.0/go.mod h1:vnRTxewy+M7BtXBNFybkuhSH4WfedVAAnERHgVFhp3k= -cosmossdk.io/schema v0.2.0 h1:UH5CR1DqUq8yP+5Np8PbvG4YX0zAUsTN2Qk6yThmfMk= -cosmossdk.io/schema v0.2.0/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= +cosmossdk.io/schema v0.3.1-0.20240930054013-7c6e0388a3f9 h1:DmOoS/1PeY6Ih0hAVlJ69kLMUrLV+TCbfICrZtB1vdU= +cosmossdk.io/schema v0.3.1-0.20240930054013-7c6e0388a3f9/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMbk2FiG/kXiLl8BRyzTWDw7gX/Hz7Dd5eDMs= @@ -286,8 +288,8 @@ github.com/hdevalence/ed25519consensus v0.2.0/go.mod h1:w3BHWjwJbFU29IRHL1Iqkw3s github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/huandu/go-assert v1.1.5 h1:fjemmA7sSfYHJD7CUqs9qTwwfdNAx7/j2/ZlHXzNB3c= github.com/huandu/go-assert v1.1.5/go.mod h1:yOLvuqZwmcHIC5rIzrBhT7D3Q9c3GFnd0JrPVhn/06U= -github.com/huandu/skiplist v1.2.0 h1:gox56QD77HzSC0w+Ws3MH3iie755GBJU1OER3h5VsYw= -github.com/huandu/skiplist v1.2.0/go.mod h1:7v3iFjLcSAzO4fN5B8dvebvo/qsfumiLiDXMrPiHF9w= +github.com/huandu/skiplist v1.2.1 h1:dTi93MgjwErA/8idWTzIw4Y1kZsMWx35fmI2c8Rij7w= +github.com/huandu/skiplist v1.2.1/go.mod h1:7v3iFjLcSAzO4fN5B8dvebvo/qsfumiLiDXMrPiHF9w= github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI= github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= @@ -399,8 +401,8 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= -github.com/prometheus/client_golang v1.20.3 h1:oPksm4K8B+Vt35tUhw6GbSNSgVlVSBH0qELP/7u83l4= -github.com/prometheus/client_golang v1.20.3/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_golang v1.20.4 h1:Tgh3Yr67PaOv/uTqloMsCEdeuFTatm5zIq5+qNN23vI= +github.com/prometheus/client_golang v1.20.4/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -409,8 +411,8 @@ github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= -github.com/prometheus/common v0.59.1 h1:LXb1quJHWm1P6wq/U824uxYi4Sg0oGvNeUm1z5dJoX0= -github.com/prometheus/common v0.59.1/go.mod h1:GpWM7dewqmVYcd7SmRaiWVe9SSqjf0UrwnYnpEZNuT0= +github.com/prometheus/common v0.60.0 h1:+V9PAREWNvJMAuJ1x1BaWl9dewMW4YrHZQbx0sJNllA= +github.com/prometheus/common v0.60.0/go.mod h1:h0LYf1R1deLSKtD4Vdg8gy4RuOvENW2J/h19V5NADQw= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/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= @@ -629,10 +631,10 @@ google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEY google.golang.org/genproto v0.0.0-20220314164441-57ef72a4c106/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E= google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de h1:F6qOa9AZTYJXOUEr4jDysRDLrm4PHePlge4v4TGAlxY= google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:VUhTRKeHn9wwcdrk73nvdC9gF178Tzhmt/qyaFcPLSo= -google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 h1:+rdxYoE3E5htTEWIe15GlN6IfvbURM//Jt0mmkmm6ZU= -google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117/go.mod h1:OimBR/bc1wPO9iV4NC2bpyjy3VnAwZh5EBPQdtaE5oo= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:pPJltXNxVzT4pK9yD8vR9X75DaWYYmLGMsEvBfFQZzQ= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= +google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 h1:wKguEg1hsxI2/L3hUYrpo1RVi48K+uTyzKqprwLXsb8= +google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142/go.mod h1:d6be+8HhtEtucleCbxpPW9PA9XwISACu8nvpPqF0BVo= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f h1:cUMEy+8oS78BWIH9OWazBkzbr090Od9tWBNtZHkOhf0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= @@ -643,8 +645,8 @@ google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= -google.golang.org/grpc v1.66.2 h1:3QdXkuq3Bkh7w+ywLdLvM56cmGvQHUMZpiCzt6Rqaoo= -google.golang.org/grpc v1.66.2/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y= +google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E= +google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= 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= diff --git a/go.work.example b/go.work.example index 834c86da2181..ebc3f15e4f8d 100644 --- a/go.work.example +++ b/go.work.example @@ -26,7 +26,9 @@ use ( ./tools/confix ./tools/hubl ./x/accounts + ./x/accounts/defaults/base ./x/accounts/defaults/lockup + ./x/accounts/defaults/multisig ./x/auth ./x/authz ./x/bank diff --git a/indexer/postgres/go.mod b/indexer/postgres/go.mod index b0423dde0744..c13699a1677a 100644 --- a/indexer/postgres/go.mod +++ b/indexer/postgres/go.mod @@ -8,6 +8,6 @@ go 1.12 // so there are no problems building this with any version of the SDK. // This module should only use the golang standard library (database/sql) // and cosmossdk.io/indexer/base. -require cosmossdk.io/schema v0.1.1 +require cosmossdk.io/schema v0.3.0 replace cosmossdk.io/schema => ../../schema diff --git a/indexer/postgres/indexer.go b/indexer/postgres/indexer.go index bfaac25842e5..a4a35d730b67 100644 --- a/indexer/postgres/indexer.go +++ b/indexer/postgres/indexer.go @@ -3,8 +3,8 @@ package postgres import ( "context" "database/sql" - "encoding/json" "errors" + "fmt" "cosmossdk.io/schema/indexer" "cosmossdk.io/schema/logutil" @@ -21,8 +21,6 @@ type Config struct { DisableRetainDeletions bool `json:"disable_retain_deletions"` } -type SqlLogger = func(msg, sql string, params ...interface{}) - type indexerImpl struct { ctx context.Context db *sql.DB @@ -32,10 +30,17 @@ type indexerImpl struct { logger logutil.Logger } -func StartIndexer(params indexer.InitParams) (indexer.InitResult, error) { - config, err := decodeConfig(params.Config.Config) - if err != nil { - return indexer.InitResult{}, err +func init() { + indexer.Register("postgres", indexer.Initializer{ + InitFunc: startIndexer, + ConfigType: Config{}, + }) +} + +func startIndexer(params indexer.InitParams) (indexer.InitResult, error) { + config, ok := params.Config.Config.(Config) + if !ok { + return indexer.InitResult{}, fmt.Errorf("invalid config type, expected %T got %T", Config{}, params.Config.Config) } ctx := params.Context @@ -89,18 +94,3 @@ func StartIndexer(params indexer.InitParams) (indexer.InitResult, error) { View: idx, }, nil } - -func decodeConfig(rawConfig map[string]interface{}) (*Config, error) { - bz, err := json.Marshal(rawConfig) - if err != nil { - return nil, err - } - - var config Config - err = json.Unmarshal(bz, &config) - if err != nil { - return nil, err - } - - return &config, nil -} diff --git a/indexer/postgres/select.go b/indexer/postgres/select.go index 242891c1cc75..8efef56c25c5 100644 --- a/indexer/postgres/select.go +++ b/indexer/postgres/select.go @@ -14,7 +14,7 @@ import ( "cosmossdk.io/schema" ) -// Count returns the number of rows in the table. +// count returns the number of rows in the table. func (tm *objectIndexer) count(ctx context.Context, conn dbConn) (int, error) { sqlStr := fmt.Sprintf("SELECT COUNT(*) FROM %q;", tm.tableName()) if tm.options.logger != nil { diff --git a/indexer/postgres/tests/config.go b/indexer/postgres/tests/config.go deleted file mode 100644 index 78e41f6059b5..000000000000 --- a/indexer/postgres/tests/config.go +++ /dev/null @@ -1,26 +0,0 @@ -package tests - -import ( - "encoding/json" - - "cosmossdk.io/indexer/postgres" - "cosmossdk.io/schema/indexer" -) - -func postgresConfigToIndexerConfig(cfg postgres.Config) (indexer.Config, error) { - cfgBz, err := json.Marshal(cfg) - if err != nil { - return indexer.Config{}, err - } - - var cfgMap map[string]interface{} - err = json.Unmarshal(cfgBz, &cfgMap) - if err != nil { - return indexer.Config{}, err - } - - return indexer.Config{ - Type: "postgres", - Config: cfgMap, - }, nil -} diff --git a/indexer/postgres/tests/go.mod b/indexer/postgres/tests/go.mod index c7a0c1e535fb..b02fb01dd8aa 100644 --- a/indexer/postgres/tests/go.mod +++ b/indexer/postgres/tests/go.mod @@ -4,7 +4,7 @@ go 1.23 require ( cosmossdk.io/indexer/postgres v0.0.0-00010101000000-000000000000 - cosmossdk.io/schema v0.1.1 + cosmossdk.io/schema v0.3.0 cosmossdk.io/schema/testing v0.0.0 github.com/fergusstrange/embedded-postgres v1.29.0 github.com/hashicorp/consul/sdk v0.16.1 diff --git a/indexer/postgres/tests/init_schema_test.go b/indexer/postgres/tests/init_schema_test.go index 4257f37d5ab7..e3fef06fc265 100644 --- a/indexer/postgres/tests/init_schema_test.go +++ b/indexer/postgres/tests/init_schema_test.go @@ -33,17 +33,20 @@ func testInitSchema(t *testing.T, disableRetainDeletions bool, goldenFileName st connectionUrl := createTestDB(t) buf := &strings.Builder{} - - cfg, err := postgresConfigToIndexerConfig(postgres.Config{ - DatabaseURL: connectionUrl, - DisableRetainDeletions: disableRetainDeletions, - }) - require.NoError(t, err) - - res, err := postgres.StartIndexer(indexer.InitParams{ - Config: cfg, + res, err := indexer.StartIndexing(indexer.IndexingOptions{ + Config: indexer.IndexingConfig{ + Target: map[string]indexer.Config{ + "postgres": { + Type: "postgres", + Config: postgres.Config{ + DatabaseURL: connectionUrl, + DisableRetainDeletions: disableRetainDeletions, + }, + }, + }, + }, Context: context.Background(), - Logger: &prettyLogger{buf}, + Logger: prettyLogger{buf}, }) require.NoError(t, err) listener := res.Listener diff --git a/indexer/postgres/tests/postgres_test.go b/indexer/postgres/tests/postgres_test.go index 0d5207ddcd92..6256f83db31c 100644 --- a/indexer/postgres/tests/postgres_test.go +++ b/indexer/postgres/tests/postgres_test.go @@ -52,24 +52,29 @@ func testPostgresIndexer(t *testing.T, retainDeletions bool) { require.NoError(t, err) }) - cfg, err := postgresConfigToIndexerConfig(postgres.Config{ - DatabaseURL: dbUrl, - DisableRetainDeletions: !retainDeletions, - }) - require.NoError(t, err) - debugLog := &strings.Builder{} - pgIndexer, err := postgres.StartIndexer(indexer.InitParams{ - Config: cfg, + res, err := indexer.StartIndexing(indexer.IndexingOptions{ + Config: indexer.IndexingConfig{ + Target: map[string]indexer.Config{ + "postgres": { + Type: "postgres", + Config: postgres.Config{ + DatabaseURL: dbUrl, + DisableRetainDeletions: !retainDeletions, + }, + }, + }, + }, Context: ctx, Logger: &prettyLogger{debugLog}, AddressCodec: addressutil.HexAddressCodec{}, }) require.NoError(t, err) + require.NoError(t, err) sim, err := appdatasim.NewSimulator(appdatasim.Options{ - Listener: pgIndexer.Listener, + Listener: res.Listener, AppSchema: indexertesting.ExampleAppSchema, StateSimOptions: statesim.Options{ CanRetainDeletions: retainDeletions, @@ -77,6 +82,9 @@ func testPostgresIndexer(t *testing.T, retainDeletions bool) { }) require.NoError(t, err) + pgIndexerView := res.IndexerInfos["postgres"].View + require.NotNil(t, pgIndexerView) + blockDataGen := sim.BlockDataGenN(10, 100) numBlocks := 200 if testing.Short() { @@ -93,7 +101,7 @@ func testPostgresIndexer(t *testing.T, retainDeletions bool) { require.NoError(t, sim.ProcessBlockData(blockData), debugLog.String()) // compare the expected state in the simulator to the actual state in the indexer and expect the diff to be empty - require.Empty(t, appdatasim.DiffAppData(sim, pgIndexer.View), debugLog.String()) + require.Empty(t, appdatasim.DiffAppData(sim, pgIndexerView), debugLog.String()) // reset the debug log after each successful block so that it doesn't get too long when debugging debugLog.Reset() diff --git a/indexer/postgres/tests/testdata/init_schema.txt b/indexer/postgres/tests/testdata/init_schema.txt index 4d18d2fb23b1..43b91a6a7a83 100644 --- a/indexer/postgres/tests/testdata/init_schema.txt +++ b/indexer/postgres/tests/testdata/init_schema.txt @@ -1,3 +1,7 @@ +INFO: Starting indexing +INFO: Starting indexer + target_name: postgres + type: postgres DEBUG: Creating enum type sql: CREATE TYPE "test_my_enum" AS ENUM ('a', 'b', 'c'); DEBUG: Creating enum type diff --git a/indexer/postgres/tests/testdata/init_schema_no_retain_delete.txt b/indexer/postgres/tests/testdata/init_schema_no_retain_delete.txt index 0ec17ae1ea1d..71dfd4d08290 100644 --- a/indexer/postgres/tests/testdata/init_schema_no_retain_delete.txt +++ b/indexer/postgres/tests/testdata/init_schema_no_retain_delete.txt @@ -1,3 +1,7 @@ +INFO: Starting indexing +INFO: Starting indexer + target_name: postgres + type: postgres DEBUG: Creating enum type sql: CREATE TYPE "test_my_enum" AS ENUM ('a', 'b', 'c'); DEBUG: Creating enum type diff --git a/math/dec_internal_test.go b/math/dec_internal_test.go index 8b899300e3b0..5273edfc9b5e 100644 --- a/math/dec_internal_test.go +++ b/math/dec_internal_test.go @@ -90,7 +90,6 @@ func (s *decimalInternalTestSuite) TestDecMarshalJSON() { {"12340Int", LegacyNewDec(12340), "\"12340.000000000000000000\"", false}, } for _, tt := range tests { - tt := tt s.T().Run(tt.name, func(t *testing.T) { got, err := tt.d.MarshalJSON() if (err != nil) != tt.wantErr { diff --git a/math/dec_test.go b/math/dec_test.go index 1e72e173e84f..90d610199f3f 100644 --- a/math/dec_test.go +++ b/math/dec_test.go @@ -261,7 +261,7 @@ func (s *decimalTestSuite) TestArithmetic() { } for tcIndex, tc := range tests { - tc := tc + resAdd := tc.d1.Add(tc.d2) resSub := tc.d1.Sub(tc.d2) resMul := tc.d1.Mul(tc.d2) @@ -727,7 +727,6 @@ func TestFormatDec(t *testing.T) { require.NoError(t, err) for _, tc := range testcases { - tc := tc t.Run(tc[0], func(t *testing.T) { out, err := math.FormatDec(tc[0]) require.NoError(t, err) @@ -1026,3 +1025,43 @@ func TestQuoMut(t *testing.T) { }) } } + +func Test_DocumentLegacyAsymmetry(t *testing.T) { + zeroDec := math.LegacyZeroDec() + emptyDec := math.LegacyDec{} + + zeroDecBz, err := zeroDec.Marshal() + require.NoError(t, err) + zeroDecJSON, err := zeroDec.MarshalJSON() + require.NoError(t, err) + + emptyDecBz, err := emptyDec.Marshal() + require.NoError(t, err) + emptyDecJSON, err := emptyDec.MarshalJSON() + require.NoError(t, err) + + // makes sense, zero and empty are semantically different and render differently + require.NotEqual(t, zeroDecJSON, emptyDecJSON) + // but on the proto wire they encode to the same bytes + require.Equal(t, zeroDecBz, emptyDecBz) + + // zero values are symmetrical + zeroDecRoundTrip := math.LegacyDec{} + err = zeroDecRoundTrip.Unmarshal(zeroDecBz) + require.NoError(t, err) + zeroDecRoundTripJSON, err := zeroDecRoundTrip.MarshalJSON() + require.NoError(t, err) + require.Equal(t, zeroDecJSON, zeroDecRoundTripJSON) + require.Equal(t, zeroDec, zeroDecRoundTrip) + + // empty values are not + emptyDecRoundTrip := math.LegacyDec{} + err = emptyDecRoundTrip.Unmarshal(emptyDecBz) + require.NoError(t, err) + emptyDecRoundTripJSON, err := emptyDecRoundTrip.MarshalJSON() + require.NoError(t, err) + + // !!! this is the key point, they are not equal, it looks like a bug + require.NotEqual(t, emptyDecJSON, emptyDecRoundTripJSON) + require.NotEqual(t, emptyDec, emptyDecRoundTrip) +} diff --git a/math/int_test.go b/math/int_test.go index 714ef5e65e50..36c2e453ea06 100644 --- a/math/int_test.go +++ b/math/int_test.go @@ -591,7 +591,6 @@ func TestFormatIntCorrectness(t *testing.T) { } for _, tt := range tests { - tt := tt t.Run(tt.in, func(t *testing.T) { got, err := math.FormatInt(tt.in) if err != nil { diff --git a/math/uint_test.go b/math/uint_test.go index 93abdf886dae..b02b442159b3 100644 --- a/math/uint_test.go +++ b/math/uint_test.go @@ -244,7 +244,7 @@ func (s *uintTestSuite) TestSafeSub() { } for i, tc := range testCases { - tc := tc + if tc.panic { s.Require().Panics(func() { tc.x.Sub(tc.y) }) continue diff --git a/orm/encoding/ormfield/duration_test.go b/orm/encoding/ormfield/duration_test.go index 485605ee0c1b..6f612ef1a1aa 100644 --- a/orm/encoding/ormfield/duration_test.go +++ b/orm/encoding/ormfield/duration_test.go @@ -140,7 +140,6 @@ func TestDurationOutOfRange(t *testing.T) { }, } for _, tc := range tt { - tc := tc t.Run(tc.name, func(t *testing.T) { t.Parallel() val := protoreflect.ValueOfMessage(tc.dur.ProtoReflect()) @@ -272,7 +271,6 @@ func TestDurationCompare(t *testing.T) { } for _, tc := range tt { - tc := tc t.Run(tc.name, func(t *testing.T) { t.Parallel() diff --git a/orm/encoding/ormfield/timestamp_test.go b/orm/encoding/ormfield/timestamp_test.go index 52b7caeadacd..401e940b2762 100644 --- a/orm/encoding/ormfield/timestamp_test.go +++ b/orm/encoding/ormfield/timestamp_test.go @@ -114,7 +114,6 @@ func TestTimestampOutOfRange(t *testing.T) { }, } for _, tc := range tt { - tc := tc t.Run(tc.name, func(t *testing.T) { t.Parallel() val := protoreflect.ValueOfMessage(tc.ts.ProtoReflect()) diff --git a/orm/go.mod b/orm/go.mod index bbaab608c46f..8bd1d5f47d99 100644 --- a/orm/go.mod +++ b/orm/go.mod @@ -3,8 +3,9 @@ module cosmossdk.io/orm go 1.23 require ( - cosmossdk.io/api v0.7.5 - cosmossdk.io/core v1.0.0-alpha.2 + cosmossdk.io/api v0.7.6 + cosmossdk.io/core v1.0.0-alpha.3 + cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29 cosmossdk.io/depinject v1.0.0 cosmossdk.io/errors v1.0.1 github.com/cosmos/cosmos-db v1.0.3-0.20240829004618-717cba019b33 @@ -14,15 +15,16 @@ require ( github.com/iancoleman/strcase v0.3.0 github.com/regen-network/gocuke v1.1.1 github.com/stretchr/testify v1.9.0 - golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 - google.golang.org/grpc v1.66.2 + golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 + google.golang.org/grpc v1.67.1 google.golang.org/protobuf v1.34.2 gotest.tools/v3 v3.5.1 pgregory.net/rapid v1.1.0 ) require ( - github.com/DataDog/zstd v1.5.5 // indirect + cosmossdk.io/schema v0.3.0 // indirect + github.com/DataDog/zstd v1.4.5 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bmatcuk/doublestar/v4 v4.6.1 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect @@ -38,32 +40,34 @@ require ( github.com/cucumber/tag-expressions/go/v6 v6.1.0 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect - github.com/getsentry/sentry-go v0.27.0 // indirect + github.com/getsentry/sentry-go v0.18.0 // indirect github.com/gofrs/uuid v4.4.0+incompatible // indirect github.com/gogo/protobuf v1.3.2 // indirect + github.com/golang/protobuf v1.5.4 // indirect github.com/golang/snappy v0.0.4 // indirect github.com/google/btree v1.1.2 // indirect - github.com/klauspost/compress v1.17.9 // indirect + github.com/klauspost/compress v1.17.10 // indirect github.com/kr/pretty v0.3.1 // indirect github.com/kr/text v0.2.0 // indirect - github.com/linxGnu/grocksdb v1.9.3 // indirect + github.com/linxGnu/grocksdb v1.8.12 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/onsi/gomega v1.20.0 // indirect github.com/pkg/errors v0.9.1 // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/prometheus/client_golang v1.20.3 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect + github.com/prometheus/client_golang v1.20.4 // indirect github.com/prometheus/client_model v0.6.1 // indirect - github.com/prometheus/common v0.59.1 // indirect + github.com/prometheus/common v0.60.0 // indirect github.com/prometheus/procfs v0.15.1 // indirect github.com/rogpeppe/go-internal v1.12.0 // indirect github.com/spf13/cast v1.7.0 // indirect github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d // indirect github.com/tendermint/go-amino v0.16.0 // indirect + github.com/tidwall/btree v1.7.0 // indirect golang.org/x/net v0.29.0 // indirect golang.org/x/sys v0.25.0 // indirect golang.org/x/text v0.18.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f // indirect gopkg.in/yaml.v3 v3.0.1 // indirect sigs.k8s.io/yaml v1.4.0 // indirect ) diff --git a/orm/go.sum b/orm/go.sum index 986912fd8e4e..0635f05e49b4 100644 --- a/orm/go.sum +++ b/orm/go.sum @@ -1,13 +1,17 @@ -cosmossdk.io/api v0.7.5 h1:eMPTReoNmGUm8DeiQL9DyM8sYDjEhWzL1+nLbI9DqtQ= -cosmossdk.io/api v0.7.5/go.mod h1:IcxpYS5fMemZGqyYtErK7OqvdM0C8kdW3dq8Q/XIG38= -cosmossdk.io/core v1.0.0-alpha.2 h1:epU0Xwces4Rgl5bMhHHkXGaGDcyucNGlC/JDH+Suckg= -cosmossdk.io/core v1.0.0-alpha.2/go.mod h1:abgLjeFLhtuKIYZWSPlVUgQBrKObO7ULV35KYfexE90= +cosmossdk.io/api v0.7.6 h1:PC20PcXy1xYKH2KU4RMurVoFjjKkCgYRbVAD4PdqUuY= +cosmossdk.io/api v0.7.6/go.mod h1:IcxpYS5fMemZGqyYtErK7OqvdM0C8kdW3dq8Q/XIG38= +cosmossdk.io/core v1.0.0-alpha.3 h1:pnxaYAas7llXgVz1lM7X6De74nWrhNKnB3yMKe4OUUA= +cosmossdk.io/core v1.0.0-alpha.3/go.mod h1:3u9cWq1FAVtiiCrDPpo4LhR+9V6k/ycSG4/Y/tREWCY= +cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29 h1:NxxUo0GMJUbIuVg0R70e3cbn9eFTEuMr7ev1AFvypdY= +cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29/go.mod h1:8s2tPeJtSiQuoyPmr2Ag7meikonISO4Fv4MoO8+ORrs= cosmossdk.io/depinject v1.0.0 h1:dQaTu6+O6askNXO06+jyeUAnF2/ssKwrrszP9t5q050= cosmossdk.io/depinject v1.0.0/go.mod h1:zxK/h3HgHoA/eJVtiSsoaRaRA2D5U4cJ5thIG4ssbB8= cosmossdk.io/errors v1.0.1 h1:bzu+Kcr0kS/1DuPBtUFdWjzLqyUuCiyHjyJB6srBV/0= cosmossdk.io/errors v1.0.1/go.mod h1:MeelVSZThMi4bEakzhhhE/CKqVv3nOJDA25bIqRDu/U= -github.com/DataDog/zstd v1.5.5 h1:oWf5W7GtOLgp6bciQYDmhHHjdhYkALu6S/5Ni9ZgSvQ= -github.com/DataDog/zstd v1.5.5/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= +cosmossdk.io/schema v0.3.0 h1:01lcaM4trhzZ1HQTfTV8z6Ma1GziOZ/YmdzBN3F720c= +cosmossdk.io/schema v0.3.0/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= +github.com/DataDog/zstd v1.4.5 h1:EndNeuB0l9syBZhut0wns3gV1hL8zX8LIu6ZiVHWLIQ= +github.com/DataDog/zstd v1.4.5/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bmatcuk/doublestar/v4 v4.6.1 h1:FH9SifrbvJhnlQpztAx++wlkk70QBf0iBWDwNy7PA4I= @@ -55,8 +59,8 @@ github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4 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/getsentry/sentry-go v0.27.0 h1:Pv98CIbtB3LkMWmXi4Joa5OOcwbmnX88sF5qbK3r3Ps= -github.com/getsentry/sentry-go v0.27.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY= +github.com/getsentry/sentry-go v0.18.0 h1:MtBW5H9QgdcJabtZcuJG80BMOwaBpkRDZkxRkNC1sN0= +github.com/getsentry/sentry-go v0.18.0/go.mod h1:Kgon4Mby+FJ7ZWHFUAZgVaIa8sxHtnRJRLTXZr51aKQ= github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= @@ -76,8 +80,8 @@ github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvq github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= 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/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU= @@ -99,16 +103,16 @@ github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47 github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= -github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/klauspost/compress v1.17.10 h1:oXAz+Vh0PMUvJczoi+flxpnBEPxoER1IaAnU/NMPtT0= +github.com/klauspost/compress v1.17.10/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/lib/pq v1.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw= github.com/lib/pq v1.10.7/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= -github.com/linxGnu/grocksdb v1.9.3 h1:s1cbPcOd0cU2SKXRG1nEqCOWYAELQjdqg3RVI2MH9ik= -github.com/linxGnu/grocksdb v1.9.3/go.mod h1:QYiYypR2d4v63Wj1adOOfzglnoII0gLj3PNh4fZkcFA= +github.com/linxGnu/grocksdb v1.8.12 h1:1/pCztQUOa3BX/1gR3jSZDoaKFpeHFvQ1XrqZpSvZVo= +github.com/linxGnu/grocksdb v1.8.12/go.mod h1:xZCIb5Muw+nhbDK4Y5UJuOrin5MceOuiXkVUR7vp4WY= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= @@ -131,14 +135,15 @@ github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTw github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_golang v1.20.3 h1:oPksm4K8B+Vt35tUhw6GbSNSgVlVSBH0qELP/7u83l4= -github.com/prometheus/client_golang v1.20.3/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_golang v1.20.4 h1:Tgh3Yr67PaOv/uTqloMsCEdeuFTatm5zIq5+qNN23vI= +github.com/prometheus/client_golang v1.20.4/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= -github.com/prometheus/common v0.59.1 h1:LXb1quJHWm1P6wq/U824uxYi4Sg0oGvNeUm1z5dJoX0= -github.com/prometheus/common v0.59.1/go.mod h1:GpWM7dewqmVYcd7SmRaiWVe9SSqjf0UrwnYnpEZNuT0= +github.com/prometheus/common v0.60.0 h1:+V9PAREWNvJMAuJ1x1BaWl9dewMW4YrHZQbx0sJNllA= +github.com/prometheus/common v0.60.0/go.mod h1:h0LYf1R1deLSKtD4Vdg8gy4RuOvENW2J/h19V5NADQw= github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= github.com/regen-network/gocuke v1.1.1 h1:13D3n5xLbpzA/J2ELHC9jXYq0+XyEr64A3ehjvfmBbE= @@ -158,14 +163,16 @@ github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d h1:vfofYNRScrDd github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d/go.mod h1:RRCYJbIwD5jmqPI9XoAFR0OcDxqUctll6zUj/+B4S48= github.com/tendermint/go-amino v0.16.0 h1:GyhmgQKvqF82e2oZeuMSp9JTN0N09emoSZlb2lyGa2E= github.com/tendermint/go-amino v0.16.0/go.mod h1:TQU0M1i/ImAo+tYpZi73AU3V/dKeCoMC9Sphe2ZwGME= +github.com/tidwall/btree v1.7.0 h1:L1fkJH/AuEh5zBnnBbmTwQ5Lt+bRJ5A8EWecslvo9iI= +github.com/tidwall/btree v1.7.0/go.mod h1:twD9XRA5jj9VUQGELzDO4HPQTNJsoWWfYEL+EUQ2cKY= github.com/yuin/goldmark v1.1.27/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= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 h1:LfspQV/FYTatPTr/3HzIcmiUFH7PGP+OQ6mgDYo3yuQ= -golang.org/x/exp v0.0.0-20240222234643-814bf88cf225/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc= +golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 h1:vr/HnozRka3pE4EsMEg1lgkXJkTFJCVUX+S/ZT6wYzM= +golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842/go.mod h1:XtvwrStGgqGPLc4cjQfWqZHG1YFdYs6swckp8vpsjnc= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= @@ -230,12 +237,12 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 h1:+rdxYoE3E5htTEWIe15GlN6IfvbURM//Jt0mmkmm6ZU= -google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117/go.mod h1:OimBR/bc1wPO9iV4NC2bpyjy3VnAwZh5EBPQdtaE5oo= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:pPJltXNxVzT4pK9yD8vR9X75DaWYYmLGMsEvBfFQZzQ= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= -google.golang.org/grpc v1.66.2 h1:3QdXkuq3Bkh7w+ywLdLvM56cmGvQHUMZpiCzt6Rqaoo= -google.golang.org/grpc v1.66.2/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y= +google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 h1:wKguEg1hsxI2/L3hUYrpo1RVi48K+uTyzKqprwLXsb8= +google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142/go.mod h1:d6be+8HhtEtucleCbxpPW9PA9XwISACu8nvpPqF0BVo= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f h1:cUMEy+8oS78BWIH9OWazBkzbr090Od9tWBNtZHkOhf0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= +google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E= +google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= 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= diff --git a/orm/internal/testkv/mem.go b/orm/internal/testkv/mem.go index 6958c53737de..90e6ba5af8cc 100644 --- a/orm/internal/testkv/mem.go +++ b/orm/internal/testkv/mem.go @@ -1,8 +1,7 @@ package testkv import ( - dbm "github.com/cosmos/cosmos-db" - + coretesting "cosmossdk.io/core/testing" "cosmossdk.io/orm/model/ormtable" ) @@ -11,8 +10,8 @@ import ( // are really two separate backing stores. func NewSplitMemBackend() ormtable.Backend { return ormtable.NewBackend(ormtable.BackendOptions{ - CommitmentStore: TestStore{dbm.NewMemDB()}, - IndexStore: TestStore{dbm.NewMemDB()}, + CommitmentStore: TestStore{coretesting.NewMemDB()}, + IndexStore: TestStore{coretesting.NewMemDB()}, }) } @@ -21,7 +20,7 @@ func NewSplitMemBackend() ormtable.Backend { // where only a single KV-store is available to modules. func NewSharedMemBackend() ormtable.Backend { return ormtable.NewBackend(ormtable.BackendOptions{ - CommitmentStore: TestStore{dbm.NewMemDB()}, + CommitmentStore: TestStore{coretesting.NewMemDB()}, // commit store is automatically used as the index store }) } diff --git a/orm/model/ormdb/module_test.go b/orm/model/ormdb/module_test.go index 237ff1904457..b6960d833891 100644 --- a/orm/model/ormdb/module_test.go +++ b/orm/model/ormdb/module_test.go @@ -8,7 +8,6 @@ import ( "strings" "testing" - dbm "github.com/cosmos/cosmos-db" "github.com/golang/mock/gomock" "gotest.tools/v3/assert" "gotest.tools/v3/golden" @@ -18,6 +17,7 @@ import ( ormv1alpha1 "cosmossdk.io/api/cosmos/orm/v1alpha1" "cosmossdk.io/core/genesis" corestore "cosmossdk.io/core/store" + coretesting "cosmossdk.io/core/testing" "cosmossdk.io/depinject" "cosmossdk.io/depinject/appconfig" _ "cosmossdk.io/orm" // required for ORM module registration @@ -389,13 +389,13 @@ func TestGetBackendResolver(t *testing.T) { }, }, }, ormdb.ModuleDBOptions{ - MemoryStoreService: testStoreService{db: dbm.NewMemDB()}, + MemoryStoreService: testStoreService{db: coretesting.NewMemDB()}, }) assert.NilError(t, err) } func ProvideTestRuntime() corestore.KVStoreService { - return testStoreService{db: dbm.NewMemDB()} + return testStoreService{db: coretesting.NewMemDB()} } func TestAppConfigModule(t *testing.T) { diff --git a/orm/model/ormtable/bench_test.go b/orm/model/ormtable/bench_test.go index 450d54e2af92..f16cdaace2e1 100644 --- a/orm/model/ormtable/bench_test.go +++ b/orm/model/ormtable/bench_test.go @@ -11,6 +11,7 @@ import ( "gotest.tools/v3/assert" "cosmossdk.io/core/store" + coretesting "cosmossdk.io/core/testing" "cosmossdk.io/orm/internal/testkv" "cosmossdk.io/orm/internal/testpb" "cosmossdk.io/orm/model/ormtable" @@ -241,7 +242,7 @@ func getBalance(store kv.Store, address, denom string) (*testpb.Balance, error) func BenchmarkManualInsertMemory(b *testing.B) { benchManual(b, func() (store.KVStore, error) { - return testkv.TestStore{Db: dbm.NewMemDB()}, nil + return testkv.TestStore{Db: coretesting.NewMemDB()}, nil }) } diff --git a/orm/model/ormtable/table_test.go b/orm/model/ormtable/table_test.go index f0331f5e6968..f6808d5ae38b 100644 --- a/orm/model/ormtable/table_test.go +++ b/orm/model/ormtable/table_test.go @@ -8,7 +8,6 @@ import ( "strings" "testing" - dbm "github.com/cosmos/cosmos-db" "google.golang.org/protobuf/proto" "google.golang.org/protobuf/reflect/protoreflect" "google.golang.org/protobuf/testing/protocmp" @@ -17,6 +16,7 @@ import ( "pgregory.net/rapid" queryv1beta1 "cosmossdk.io/api/cosmos/base/query/v1beta1" + coretesting "cosmossdk.io/core/testing" sdkerrors "cosmossdk.io/errors" "cosmossdk.io/orm/encoding/ormkv" "cosmossdk.io/orm/internal/testkv" @@ -742,8 +742,8 @@ func TestReadonly(t *testing.T) { }) assert.NilError(t, err) readBackend := ormtable.NewReadBackend(ormtable.ReadBackendOptions{ - CommitmentStoreReader: testkv.TestStore{Db: dbm.NewMemDB()}, - IndexStoreReader: testkv.TestStore{Db: dbm.NewMemDB()}, + CommitmentStoreReader: testkv.TestStore{Db: coretesting.NewMemDB()}, + IndexStoreReader: testkv.TestStore{Db: coretesting.NewMemDB()}, }) ctx := ormtable.WrapContextDefault(readBackend) assert.ErrorIs(t, ormerrors.ReadOnly, table.Insert(ctx, &testpb.ExampleTable{})) diff --git a/x/auth/proto/cosmos/auth/module/v1/module.proto b/proto/cosmos/auth/module/v1/module.proto similarity index 100% rename from x/auth/proto/cosmos/auth/module/v1/module.proto rename to proto/cosmos/auth/module/v1/module.proto diff --git a/proto/cosmos/auth/v1beta1/accounts.proto b/proto/cosmos/auth/v1beta1/accounts.proto new file mode 100644 index 000000000000..ade3f897bc27 --- /dev/null +++ b/proto/cosmos/auth/v1beta1/accounts.proto @@ -0,0 +1,27 @@ +syntax = "proto3"; +package cosmos.auth.v1beta1; + +import "google/protobuf/any.proto"; + +import "cosmos/auth/v1beta1/auth.proto"; + +option go_package = "github.com/cosmos/cosmos-sdk/x/auth/types"; + +// QueryLegacyAccount defines a query that can be implemented by an x/account +// to return an auth understandable representation of an account. +// This query is only used for accounts retro-compatibility at gRPC +// level, the state machine must not make any assumptions around this. +message QueryLegacyAccount {} + +// QueryLegacyAccountResponse defines the response type of the +// `QueryLegacyAccount` query. +message QueryLegacyAccountResponse { + // account represents the google.Protobuf.Any wrapped account + // the type wrapped by the any does not need to comply with the + // sdk.AccountI interface. + google.protobuf.Any account = 1; + // base represents the account as a BaseAccount, this can return + // nil if the account cannot be represented as a BaseAccount. + // This is used in the gRPC QueryAccountInfo method. + BaseAccount base = 2; +} \ No newline at end of file diff --git a/x/auth/proto/cosmos/auth/v1beta1/auth.proto b/proto/cosmos/auth/v1beta1/auth.proto similarity index 100% rename from x/auth/proto/cosmos/auth/v1beta1/auth.proto rename to proto/cosmos/auth/v1beta1/auth.proto diff --git a/x/auth/proto/cosmos/auth/v1beta1/genesis.proto b/proto/cosmos/auth/v1beta1/genesis.proto similarity index 100% rename from x/auth/proto/cosmos/auth/v1beta1/genesis.proto rename to proto/cosmos/auth/v1beta1/genesis.proto diff --git a/x/auth/proto/cosmos/auth/v1beta1/query.proto b/proto/cosmos/auth/v1beta1/query.proto similarity index 100% rename from x/auth/proto/cosmos/auth/v1beta1/query.proto rename to proto/cosmos/auth/v1beta1/query.proto diff --git a/x/auth/proto/cosmos/auth/v1beta1/tx.proto b/proto/cosmos/auth/v1beta1/tx.proto similarity index 73% rename from x/auth/proto/cosmos/auth/v1beta1/tx.proto rename to proto/cosmos/auth/v1beta1/tx.proto index bdfac0f171d3..fefe2bc6a05b 100644 --- a/x/auth/proto/cosmos/auth/v1beta1/tx.proto +++ b/proto/cosmos/auth/v1beta1/tx.proto @@ -22,6 +22,9 @@ service Msg { // NonAtomicExec allows users to submit multiple messages for non-atomic execution. rpc NonAtomicExec(MsgNonAtomicExec) returns (MsgNonAtomicExecResponse); + + // MigrateAccount migrates the account to x/accounts. + rpc MigrateAccount(MsgMigrateAccount) returns (MsgMigrateAccountResponse); } // MsgUpdateParams is the Msg/UpdateParams request type. @@ -64,3 +67,22 @@ message NonAtomicExecResult { message MsgNonAtomicExecResponse { repeated NonAtomicExecResult results = 1; } + +// MsgMigrateAccount defines a message which allows users to migrate from BaseAccount +// to other x/accounts types. +message MsgMigrateAccount { + option (amino.name) = "cosmos-sdk/x/auth/MsgMigrateAccount"; + option (cosmos.msg.v1.signer) = "signer"; + + string signer = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"]; + string account_type = 2; + google.protobuf.Any account_init_msg = 3; +} + +// MsgMigrateAccountResponse defines the response given when migrating to +// an x/accounts account. +message MsgMigrateAccountResponse { + // init_response defines the response returned by the x/account account + // initialization. + google.protobuf.Any init_response = 1; +} \ No newline at end of file diff --git a/proto/cosmos/tx/config/v1/config.proto b/proto/cosmos/tx/config/v1/config.proto index 65c6b6bbac8d..adfb28c1d7ec 100644 --- a/proto/cosmos/tx/config/v1/config.proto +++ b/proto/cosmos/tx/config/v1/config.proto @@ -9,12 +9,4 @@ message Config { option (cosmos.app.v1alpha1.module) = { go_import: "github.com/cosmos/cosmos-sdk/x/auth/tx" }; - - // skip_ante_handler defines whether the ante handler registration should be skipped in case an app wants to override - // this functionality. - bool skip_ante_handler = 1; - - // skip_post_handler defines whether the post handler registration should be skipped in case an app wants to override - // this functionality. - bool skip_post_handler = 2; } diff --git a/proto/cosmos/validate/module/v1/module.proto b/proto/cosmos/validate/module/v1/module.proto new file mode 100644 index 000000000000..f65327573112 --- /dev/null +++ b/proto/cosmos/validate/module/v1/module.proto @@ -0,0 +1,12 @@ +syntax = "proto3"; + +package cosmos.validate.module.v1; + +import "cosmos/app/v1alpha1/module.proto"; + +// Module is the config object of the x/validate module. +message Module { + option (cosmos.app.v1alpha1.module) = { + go_import: "github.com/cosmos/cosmos-sdk/x/validate" + }; +} diff --git a/runtime/app.go b/runtime/app.go index f9a74a29a208..e63da54c0e12 100644 --- a/runtime/app.go +++ b/runtime/app.go @@ -6,6 +6,8 @@ import ( "slices" abci "github.com/cometbft/cometbft/api/cometbft/abci/v1" + cmtcrypto "github.com/cometbft/cometbft/crypto" + cmted25519 "github.com/cometbft/cometbft/crypto/ed25519" "google.golang.org/grpc" runtimev1alpha1 "cosmossdk.io/api/cosmos/app/runtime/v1alpha1" @@ -30,6 +32,9 @@ import ( authtx "github.com/cosmos/cosmos-sdk/x/auth/tx" ) +// KeyGenF is a function that generates a private key for use by comet. +type KeyGenF = func() (cmtcrypto.PrivKey, error) + // App is a wrapper around BaseApp and ModuleManager that can be used in hybrid // app.go/app config scenarios or directly as a servertypes.Application instance. // To get an instance of *App, *AppBuilder must be requested as a dependency @@ -45,7 +50,7 @@ type App struct { ModuleManager *module.Manager UnorderedTxManager *unorderedtx.Manager - configurator module.Configurator // nolint:staticcheck // SA1019: Configurator is deprecated but still used in runtime v1. + configurator module.Configurator //nolint:staticcheck // SA1019: Configurator is deprecated but still used in runtime v1. config *runtimev1alpha1.Module storeKeys []storetypes.StoreKey interfaceRegistry codectypes.InterfaceRegistry @@ -251,7 +256,7 @@ func (a *App) RegisterNodeService(clientCtx client.Context, cfg config.Config) { } // Configurator returns the app's configurator. -func (a *App) Configurator() module.Configurator { // nolint:staticcheck // SA1019: Configurator is deprecated but still used in runtime v1. +func (a *App) Configurator() module.Configurator { //nolint:staticcheck // SA1019: Configurator is deprecated but still used in runtime v1. return a.configurator } @@ -308,3 +313,10 @@ var _ servertypes.Application = &App{} type hasServicesV1 interface { RegisterServices(grpc.ServiceRegistrar) error } + +// ValidatorKeyProvider returns a function that generates a private key for use by comet. +func (a *App) ValidatorKeyProvider() KeyGenF { + return func() (cmtcrypto.PrivKey, error) { + return cmted25519.GenPrivKey(), nil + } +} diff --git a/runtime/builder.go b/runtime/builder.go index 68b58b66a000..37be02fa769e 100644 --- a/runtime/builder.go +++ b/runtime/builder.go @@ -39,9 +39,18 @@ func (a *AppBuilder) Build(db corestore.KVStoreWithBatch, traceStore io.Writer, baseAppOptions = append(baseAppOptions, option) } + // set routers first in case they get modified by other options + baseAppOptions = append( + []func(*baseapp.BaseApp){ + func(bApp *baseapp.BaseApp) { + bApp.SetMsgServiceRouter(a.app.msgServiceRouter) + bApp.SetGRPCQueryRouter(a.app.grpcQueryRouter) + }, + }, + baseAppOptions..., + ) + bApp := baseapp.NewBaseApp(a.app.config.AppName, a.app.logger, db, nil, baseAppOptions...) - bApp.SetMsgServiceRouter(a.app.msgServiceRouter) - bApp.SetGRPCQueryRouter(a.app.grpcQueryRouter) bApp.SetCommitMultiStoreTracer(traceStore) bApp.SetVersion(version.Version) bApp.SetInterfaceRegistry(a.app.interfaceRegistry) diff --git a/runtime/module.go b/runtime/module.go index 95595fc209f8..773efe10a3e2 100644 --- a/runtime/module.go +++ b/runtime/module.go @@ -39,7 +39,7 @@ type appModule struct { func (m appModule) IsOnePerModuleType() {} func (m appModule) IsAppModule() {} -func (m appModule) RegisterServices(configurator module.Configurator) { // nolint:staticcheck // SA1019: Configurator is deprecated but still used in runtime v1. +func (m appModule) RegisterServices(configurator module.Configurator) { //nolint:staticcheck // SA1019: Configurator is deprecated but still used in runtime v1. err := m.app.registerRuntimeServices(configurator) if err != nil { panic(err) diff --git a/runtime/services.go b/runtime/services.go index 2f453898ff88..c36f7e3e0331 100644 --- a/runtime/services.go +++ b/runtime/services.go @@ -8,7 +8,7 @@ import ( "github.com/cosmos/cosmos-sdk/types/module" ) -func (a *App) registerRuntimeServices(cfg module.Configurator) error { // nolint:staticcheck // SA1019: Configurator is deprecated but still used in runtime v1. +func (a *App) registerRuntimeServices(cfg module.Configurator) error { //nolint:staticcheck // SA1019: Configurator is deprecated but still used in runtime v1. autocliv1.RegisterQueryServer(cfg.QueryServer(), services.NewAutoCLIQueryService(a.ModuleManager.Modules)) reflectionSvc, err := services.NewReflectionService() diff --git a/runtime/services/autocli.go b/runtime/services/autocli.go index c6b66e510d62..cd2005690d1e 100644 --- a/runtime/services/autocli.go +++ b/runtime/services/autocli.go @@ -105,7 +105,7 @@ type autocliConfigurator struct { err error } -var _ module.Configurator = &autocliConfigurator{} // nolint:staticcheck // SA1019: Configurator is deprecated but still used in runtime v1. +var _ module.Configurator = &autocliConfigurator{} //nolint:staticcheck // SA1019: Configurator is deprecated but still used in runtime v1. func (a *autocliConfigurator) MsgServer() gogogrpc.Server { return &a.msgServer } diff --git a/runtime/store.go b/runtime/store.go index a6a2866fbeb3..df2a40f06b0c 100644 --- a/runtime/store.go +++ b/runtime/store.go @@ -2,6 +2,8 @@ package runtime import ( "context" + "errors" + "fmt" "io" "cosmossdk.io/core/store" @@ -184,6 +186,11 @@ func KVStoreAdapter(store store.KVStore) storetypes.KVStore { // UpgradeStoreLoader is used to prepare baseapp with a fixed StoreLoader // pattern. This is useful for custom upgrade loading logic. func UpgradeStoreLoader(upgradeHeight int64, storeUpgrades *store.StoreUpgrades) baseapp.StoreLoader { + // sanity checks on store upgrades + if err := checkStoreUpgrade(storeUpgrades); err != nil { + panic(err) + } + return func(ms storetypes.CommitMultiStore) error { if upgradeHeight == ms.LastCommitID().Version+1 { // Check if the current commit version and upgrade height matches @@ -200,3 +207,40 @@ func UpgradeStoreLoader(upgradeHeight int64, storeUpgrades *store.StoreUpgrades) return baseapp.DefaultStoreLoader(ms) } } + +// checkStoreUpgrade performs sanity checks on the store upgrades +func checkStoreUpgrade(storeUpgrades *store.StoreUpgrades) error { + if storeUpgrades == nil { + return errors.New("store upgrades cannot be nil") + } + + // check for duplicates + addedFilter := make(map[string]struct{}) + deletedFilter := make(map[string]struct{}) + + for _, key := range storeUpgrades.Added { + if _, ok := addedFilter[key]; ok { + return fmt.Errorf("store upgrade has duplicate key %s in added", key) + } + addedFilter[key] = struct{}{} + } + for _, key := range storeUpgrades.Deleted { + if _, ok := deletedFilter[key]; ok { + return fmt.Errorf("store upgrade has duplicate key %s in deleted", key) + } + deletedFilter[key] = struct{}{} + } + + for _, key := range storeUpgrades.Added { + if _, ok := deletedFilter[key]; ok { + return fmt.Errorf("store upgrade has key %s in both added and deleted", key) + } + } + for _, key := range storeUpgrades.Deleted { + if _, ok := addedFilter[key]; ok { + return fmt.Errorf("store upgrade has key %s in both added and deleted", key) + } + } + + return nil +} diff --git a/runtime/store_test.go b/runtime/store_test.go new file mode 100644 index 000000000000..a583a08d0391 --- /dev/null +++ b/runtime/store_test.go @@ -0,0 +1,65 @@ +package runtime + +import ( + "testing" + + "github.com/stretchr/testify/require" + + corestore "cosmossdk.io/core/store" +) + +func TestCheckStoreUpgrade(t *testing.T) { + tests := []struct { + name string + storeUpgrades *corestore.StoreUpgrades + errMsg string + }{ + { + name: "Nil StoreUpgrades", + storeUpgrades: nil, + errMsg: "store upgrades cannot be nil", + }, + { + name: "Valid StoreUpgrades", + storeUpgrades: &corestore.StoreUpgrades{ + Added: []string{"store1", "store2"}, + Deleted: []string{"store3", "store4"}, + }, + }, + { + name: "Duplicate key in Added", + storeUpgrades: &corestore.StoreUpgrades{ + Added: []string{"store1", "store2", "store1"}, + Deleted: []string{"store3"}, + }, + errMsg: "store upgrade has duplicate key store1 in added", + }, + { + name: "Duplicate key in Deleted", + storeUpgrades: &corestore.StoreUpgrades{ + Added: []string{"store1"}, + Deleted: []string{"store2", "store3", "store2"}, + }, + errMsg: "store upgrade has duplicate key store2 in deleted", + }, + { + name: "Key in both Added and Deleted", + storeUpgrades: &corestore.StoreUpgrades{ + Added: []string{"store1", "store2"}, + Deleted: []string{"store2", "store3"}, + }, + errMsg: "store upgrade has key store2 in both added and deleted", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + err := checkStoreUpgrade(tt.storeUpgrades) + if tt.errMsg == "" { + require.NoError(t, err) + } else { + require.ErrorContains(t, err, tt.errMsg) + } + }) + } +} diff --git a/runtime/v2/app.go b/runtime/v2/app.go index b7104f9e4774..caf55b92ce01 100644 --- a/runtime/v2/app.go +++ b/runtime/v2/app.go @@ -5,9 +5,8 @@ import ( "errors" "slices" - gogoproto "github.com/cosmos/gogoproto/proto" - runtimev2 "cosmossdk.io/api/cosmos/app/runtime/v2" + appmodulev2 "cosmossdk.io/core/appmodule/v2" "cosmossdk.io/core/registry" "cosmossdk.io/core/transaction" "cosmossdk.io/log" @@ -43,9 +42,8 @@ type App[T transaction.Tx] struct { amino registry.AminoRegistrar moduleManager *MM[T] - // GRPCMethodsToMessageMap maps gRPC method name to a function that decodes the request - // bytes into a gogoproto.Message, which then can be passed to appmanager. - GRPCMethodsToMessageMap map[string]func() gogoproto.Message + // QueryHandlers defines the query handlers + QueryHandlers map[string]appmodulev2.Handler storeLoader StoreLoader } @@ -120,6 +118,6 @@ func (a *App[T]) GetAppManager() *appmanager.AppManager[T] { return a.AppManager } -func (a *App[T]) GetGPRCMethodsToMessageMap() map[string]func() gogoproto.Message { - return a.GRPCMethodsToMessageMap +func (a *App[T]) GetQueryHandlers() map[string]appmodulev2.Handler { + return a.QueryHandlers } diff --git a/runtime/v2/builder.go b/runtime/v2/builder.go index 0a1b279330de..b28ddbc741b4 100644 --- a/runtime/v2/builder.go +++ b/runtime/v2/builder.go @@ -3,29 +3,25 @@ package runtime import ( "context" "encoding/json" + "errors" "fmt" "io" - "path/filepath" "cosmossdk.io/core/appmodule" appmodulev2 "cosmossdk.io/core/appmodule/v2" - "cosmossdk.io/core/server" "cosmossdk.io/core/store" "cosmossdk.io/core/transaction" + "cosmossdk.io/runtime/v2/services" "cosmossdk.io/server/v2/appmanager" "cosmossdk.io/server/v2/stf" "cosmossdk.io/server/v2/stf/branch" - "cosmossdk.io/store/v2/db" - rootstore "cosmossdk.io/store/v2/root" ) // AppBuilder is a type that is injected into a container by the runtime/v2 module // (as *AppBuilder) which can be used to create an app which is compatible with // the existing app.go initialization conventions. type AppBuilder[T transaction.Tx] struct { - app *App[T] - config server.DynamicConfig - storeOptions *rootstore.Options + app *App[T] // the following fields are used to overwrite the default branch func(state store.ReaderMap) store.WriterMap @@ -97,6 +93,10 @@ func (a *AppBuilder[T]) Build(opts ...AppBuilderOption[T]) (*App[T], error) { } } + if a.app.db == nil { + return nil, fmt.Errorf("app.db is not set, it is required to build the app") + } + if err := a.app.moduleManager.RegisterServices(a.app); err != nil { return nil, err } @@ -120,60 +120,57 @@ func (a *AppBuilder[T]) Build(opts ...AppBuilderOption[T]) (*App[T], error) { } a.app.stf = stf - home := a.config.GetString(FlagHome) - scRawDb, err := db.NewDB( - db.DBType(a.config.GetString("store.app-db-backend")), - "application", - filepath.Join(home, "data"), - nil, - ) - if err != nil { - panic(err) - } - - var storeOptions rootstore.Options - if a.storeOptions != nil { - storeOptions = *a.storeOptions - } else { - storeOptions = rootstore.DefaultStoreOptions() - } - factoryOptions := &rootstore.FactoryOptions{ - Logger: a.app.logger, - RootDir: home, - Options: storeOptions, - StoreKeys: append(a.app.storeKeys, "stf"), - SCRawDB: scRawDb, - } - - rs, err := rootstore.CreateRootStore(factoryOptions) - if err != nil { - return nil, fmt.Errorf("failed to create root store: %w", err) - } - a.app.db = rs - appManagerBuilder := appmanager.Builder[T]{ STF: a.app.stf, DB: a.app.db, ValidateTxGasLimit: a.app.config.GasConfig.ValidateTxGasLimit, QueryGasLimit: a.app.config.GasConfig.QueryGasLimit, SimulationGasLimit: a.app.config.GasConfig.SimulationGasLimit, - InitGenesis: func(ctx context.Context, src io.Reader, txHandler func(json.RawMessage) error) error { + InitGenesis: func( + ctx context.Context, + src io.Reader, + txHandler func(json.RawMessage) error, + ) (store.WriterMap, error) { // this implementation assumes that the state is a JSON object bz, err := io.ReadAll(src) if err != nil { - return fmt.Errorf("failed to read import state: %w", err) + return nil, fmt.Errorf("failed to read import state: %w", err) } - var genesisState map[string]json.RawMessage - if err = json.Unmarshal(bz, &genesisState); err != nil { - return err + var genesisJSON map[string]json.RawMessage + if err = json.Unmarshal(bz, &genesisJSON); err != nil { + return nil, err } - if err = a.app.moduleManager.InitGenesisJSON(ctx, genesisState, txHandler); err != nil { - return fmt.Errorf("failed to init genesis: %w", err) + + v, zeroState, err := a.app.db.StateLatest() + if err != nil { + return nil, fmt.Errorf("unable to get latest state: %w", err) } - return nil + if v != 0 { // TODO: genesis state may be > 0, we need to set version on store + return nil, errors.New("cannot init genesis on non-zero state") + } + genesisCtx := services.NewGenesisContext(a.branch(zeroState)) + genesisState, err := genesisCtx.Run(ctx, func(ctx context.Context) error { + err = a.app.moduleManager.InitGenesisJSON(ctx, genesisJSON, txHandler) + if err != nil { + return fmt.Errorf("failed to init genesis: %w", err) + } + return nil + }) + + return genesisState, err }, ExportGenesis: func(ctx context.Context, version uint64) ([]byte, error) { - genesisJson, err := a.app.moduleManager.ExportGenesisForModules(ctx) + state, err := a.app.db.StateAt(version) + if err != nil { + return nil, fmt.Errorf("unable to get state at given version: %w", err) + } + + genesisJson, err := a.app.moduleManager.ExportGenesisForModules( + ctx, + func() store.WriterMap { + return a.branch(state) + }, + ) if err != nil { return nil, fmt.Errorf("failed to export genesis: %w", err) } @@ -221,9 +218,3 @@ func AppBuilderWithPostTxExec[T transaction.Tx](postTxExec func(ctx context.Cont a.postTxExec = postTxExec } } - -func AppBuilderWithStoreOptions[T transaction.Tx](opts *rootstore.Options) AppBuilderOption[T] { - return func(a *AppBuilder[T]) { - a.storeOptions = opts - } -} diff --git a/runtime/v2/go.mod b/runtime/v2/go.mod index 4327d9d1c3e9..1bd24cd1e26c 100644 --- a/runtime/v2/go.mod +++ b/runtime/v2/go.mod @@ -5,7 +5,6 @@ go 1.23 // server v2 integration replace ( cosmossdk.io/api => ../../api - cosmossdk.io/core/testing => ../../core/testing cosmossdk.io/server/v2/appmanager => ../../server/v2/appmanager cosmossdk.io/server/v2/stf => ../../server/v2/stf cosmossdk.io/store/v2 => ../../store/v2 @@ -13,8 +12,8 @@ replace ( ) require ( - cosmossdk.io/api v0.7.5 - cosmossdk.io/core v1.0.0-alpha.2 + cosmossdk.io/api v0.7.6 + cosmossdk.io/core v1.0.0-alpha.4 cosmossdk.io/depinject v1.0.0 cosmossdk.io/log v1.4.1 cosmossdk.io/server/v2/appmanager v0.0.0-00010101000000-000000000000 @@ -22,15 +21,16 @@ require ( cosmossdk.io/store/v2 v2.0.0-00010101000000-000000000000 cosmossdk.io/x/tx v0.13.3 github.com/cosmos/gogoproto v1.7.0 - google.golang.org/grpc v1.66.2 + google.golang.org/grpc v1.67.1 google.golang.org/protobuf v1.34.2 ) require ( buf.build/gen/go/cometbft/cometbft/protocolbuffers/go v1.34.2-20240701160653-fedbb9acfd2f.2 // indirect buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.34.2-20240130113600-88ef6483f90f.2 // indirect - cosmossdk.io/core/testing v0.0.0-00010101000000-000000000000 // indirect + cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29 // indirect cosmossdk.io/errors/v2 v2.0.0-20240731132947-df72853b3ca5 // indirect + cosmossdk.io/schema v0.3.0 // indirect github.com/DataDog/zstd v1.5.5 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect @@ -63,9 +63,9 @@ require ( github.com/onsi/gomega v1.28.1 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/client_golang v1.20.3 // indirect + github.com/prometheus/client_golang v1.20.4 // indirect github.com/prometheus/client_model v0.6.1 // indirect - github.com/prometheus/common v0.59.1 // indirect + github.com/prometheus/common v0.60.0 // indirect github.com/prometheus/procfs v0.15.1 // indirect github.com/rogpeppe/go-internal v1.12.0 // indirect github.com/rs/zerolog v1.33.0 // indirect @@ -80,8 +80,8 @@ require ( golang.org/x/sync v0.8.0 // indirect golang.org/x/sys v0.25.0 // indirect golang.org/x/text v0.18.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f // indirect gopkg.in/yaml.v3 v3.0.1 // indirect sigs.k8s.io/yaml v1.4.0 // indirect ) diff --git a/runtime/v2/go.sum b/runtime/v2/go.sum index 30d27ab50056..b273f05e2e32 100644 --- a/runtime/v2/go.sum +++ b/runtime/v2/go.sum @@ -2,14 +2,18 @@ buf.build/gen/go/cometbft/cometbft/protocolbuffers/go v1.34.2-20240701160653-fed buf.build/gen/go/cometbft/cometbft/protocolbuffers/go v1.34.2-20240701160653-fedbb9acfd2f.2/go.mod h1:1+3gJj2NvZ1mTLAtHu+lMhOjGgQPiCKCeo+9MBww0Eo= buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.34.2-20240130113600-88ef6483f90f.2 h1:b7EEYTUHmWSBEyISHlHvXbJPqtKiHRuUignL1tsHnNQ= buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.34.2-20240130113600-88ef6483f90f.2/go.mod h1:HqcXMSa5qnNuakaMUo+hWhF51mKbcrZxGl9Vp5EeJXc= -cosmossdk.io/core v1.0.0-alpha.2 h1:epU0Xwces4Rgl5bMhHHkXGaGDcyucNGlC/JDH+Suckg= -cosmossdk.io/core v1.0.0-alpha.2/go.mod h1:abgLjeFLhtuKIYZWSPlVUgQBrKObO7ULV35KYfexE90= +cosmossdk.io/core v1.0.0-alpha.4 h1:9iuroT9ejDYETCsGkzkvs/wAY/5UFl7nCIINFRxyMJY= +cosmossdk.io/core v1.0.0-alpha.4/go.mod h1:3u9cWq1FAVtiiCrDPpo4LhR+9V6k/ycSG4/Y/tREWCY= +cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29 h1:NxxUo0GMJUbIuVg0R70e3cbn9eFTEuMr7ev1AFvypdY= +cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29/go.mod h1:8s2tPeJtSiQuoyPmr2Ag7meikonISO4Fv4MoO8+ORrs= cosmossdk.io/depinject v1.0.0 h1:dQaTu6+O6askNXO06+jyeUAnF2/ssKwrrszP9t5q050= cosmossdk.io/depinject v1.0.0/go.mod h1:zxK/h3HgHoA/eJVtiSsoaRaRA2D5U4cJ5thIG4ssbB8= cosmossdk.io/errors/v2 v2.0.0-20240731132947-df72853b3ca5 h1:IQNdY2kB+k+1OM2DvqFG1+UgeU1JzZrWtwuWzI3ZfwA= cosmossdk.io/errors/v2 v2.0.0-20240731132947-df72853b3ca5/go.mod h1:0CuYKkFHxc1vw2JC+t21THBCALJVROrWVR/3PQ1urpc= cosmossdk.io/log v1.4.1 h1:wKdjfDRbDyZRuWa8M+9nuvpVYxrEOwbD/CA8hvhU8QM= cosmossdk.io/log v1.4.1/go.mod h1:k08v0Pyq+gCP6phvdI6RCGhLf/r425UT6Rk/m+o74rU= +cosmossdk.io/schema v0.3.0 h1:01lcaM4trhzZ1HQTfTV8z6Ma1GziOZ/YmdzBN3F720c= +cosmossdk.io/schema v0.3.0/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/DataDog/zstd v1.5.5 h1:oWf5W7GtOLgp6bciQYDmhHHjdhYkALu6S/5Ni9ZgSvQ= github.com/DataDog/zstd v1.5.5/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= @@ -189,8 +193,8 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= -github.com/prometheus/client_golang v1.20.3 h1:oPksm4K8B+Vt35tUhw6GbSNSgVlVSBH0qELP/7u83l4= -github.com/prometheus/client_golang v1.20.3/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_golang v1.20.4 h1:Tgh3Yr67PaOv/uTqloMsCEdeuFTatm5zIq5+qNN23vI= +github.com/prometheus/client_golang v1.20.4/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -198,8 +202,8 @@ github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= -github.com/prometheus/common v0.59.1 h1:LXb1quJHWm1P6wq/U824uxYi4Sg0oGvNeUm1z5dJoX0= -github.com/prometheus/common v0.59.1/go.mod h1:GpWM7dewqmVYcd7SmRaiWVe9SSqjf0UrwnYnpEZNuT0= +github.com/prometheus/common v0.60.0 h1:+V9PAREWNvJMAuJ1x1BaWl9dewMW4YrHZQbx0sJNllA= +github.com/prometheus/common v0.60.0/go.mod h1:h0LYf1R1deLSKtD4Vdg8gy4RuOvENW2J/h19V5NADQw= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/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= @@ -311,12 +315,12 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 h1:+rdxYoE3E5htTEWIe15GlN6IfvbURM//Jt0mmkmm6ZU= -google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117/go.mod h1:OimBR/bc1wPO9iV4NC2bpyjy3VnAwZh5EBPQdtaE5oo= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:pPJltXNxVzT4pK9yD8vR9X75DaWYYmLGMsEvBfFQZzQ= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= -google.golang.org/grpc v1.66.2 h1:3QdXkuq3Bkh7w+ywLdLvM56cmGvQHUMZpiCzt6Rqaoo= -google.golang.org/grpc v1.66.2/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y= +google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 h1:wKguEg1hsxI2/L3hUYrpo1RVi48K+uTyzKqprwLXsb8= +google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142/go.mod h1:d6be+8HhtEtucleCbxpPW9PA9XwISACu8nvpPqF0BVo= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f h1:cUMEy+8oS78BWIH9OWazBkzbr090Od9tWBNtZHkOhf0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= +google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E= +google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= 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= diff --git a/runtime/v2/manager.go b/runtime/v2/manager.go index eea180843800..01b0c93971ab 100644 --- a/runtime/v2/manager.go +++ b/runtime/v2/manager.go @@ -21,8 +21,10 @@ import ( "cosmossdk.io/core/appmodule" appmodulev2 "cosmossdk.io/core/appmodule/v2" "cosmossdk.io/core/registry" + "cosmossdk.io/core/store" "cosmossdk.io/core/transaction" "cosmossdk.io/log" + "cosmossdk.io/runtime/v2/services" "cosmossdk.io/server/v2/stf" ) @@ -193,6 +195,7 @@ func (m *MM[T]) InitGenesisJSON( // ExportGenesisForModules performs export genesis functionality for modules func (m *MM[T]) ExportGenesisForModules( ctx context.Context, + stateFactory func() store.WriterMap, modulesToExport ...string, ) (map[string]json.RawMessage, error) { if len(modulesToExport) == 0 { @@ -203,17 +206,19 @@ func (m *MM[T]) ExportGenesisForModules( return nil, err } + type genesisResult struct { + bz json.RawMessage + err error + } + type ModuleI interface { ExportGenesis(ctx context.Context) (json.RawMessage, error) } - genesisData := make(map[string]json.RawMessage) - - // TODO: make async export genesis https://github.com/cosmos/cosmos-sdk/issues/21303 + channels := make(map[string]chan genesisResult) for _, moduleName := range modulesToExport { mod := m.modules[moduleName] var moduleI ModuleI - if module, hasGenesis := mod.(appmodulev2.HasGenesis); hasGenesis { moduleI = module.(ModuleI) } else if module, hasABCIGenesis := mod.(appmodulev2.HasABCIGenesis); hasABCIGenesis { @@ -222,12 +227,29 @@ func (m *MM[T]) ExportGenesisForModules( continue } - res, err := moduleI.ExportGenesis(ctx) - if err != nil { - return nil, err + channels[moduleName] = make(chan genesisResult) + go func(moduleI ModuleI, ch chan genesisResult) { + genesisCtx := services.NewGenesisContext(stateFactory()) + _, _ = genesisCtx.Run(ctx, func(ctx context.Context) error { + jm, err := moduleI.ExportGenesis(ctx) + if err != nil { + ch <- genesisResult{nil, err} + return err + } + ch <- genesisResult{jm, nil} + return nil + }) + }(moduleI, channels[moduleName]) + } + + genesisData := make(map[string]json.RawMessage) + for moduleName := range channels { + res := <-channels[moduleName] + if res.err != nil { + return nil, fmt.Errorf("genesis export error in %s: %w", moduleName, res.err) } - genesisData[moduleName] = res + genesisData[moduleName] = res.bz } return genesisData, nil @@ -459,10 +481,8 @@ func (m *MM[T]) RunMigrations(ctx context.Context, fromVM appmodulev2.VersionMap func (m *MM[T]) RegisterServices(app *App[T]) error { for _, module := range m.modules { // register msg + query - if services, ok := module.(hasServicesV1); ok { - if err := registerServices(services, app, protoregistry.GlobalFiles); err != nil { - return err - } + if err := registerServices(module, app, protoregistry.GlobalFiles); err != nil { + return err } // register migrations @@ -577,7 +597,6 @@ func (m *MM[T]) assertNoForgottenModules( } var missing []string for m := range m.modules { - m := m if pass != nil && pass(m) { continue } @@ -595,26 +614,47 @@ func (m *MM[T]) assertNoForgottenModules( return nil } -func registerServices[T transaction.Tx](s hasServicesV1, app *App[T], registry *protoregistry.Files) error { - c := &configurator{ - grpcQueryDecoders: map[string]func() gogoproto.Message{}, - stfQueryRouter: app.queryRouterBuilder, - stfMsgRouter: app.msgRouterBuilder, - registry: registry, - err: nil, - } +func registerServices[T transaction.Tx](s appmodulev2.AppModule, app *App[T], registry *protoregistry.Files) error { + // case module with services + if services, ok := s.(hasServicesV1); ok { + c := &configurator{ + queryHandlers: map[string]appmodulev2.Handler{}, + stfQueryRouter: app.queryRouterBuilder, + stfMsgRouter: app.msgRouterBuilder, + registry: registry, + err: nil, + } + if err := services.RegisterServices(c); err != nil { + return fmt.Errorf("unable to register services: %w", err) + } + + if c.err != nil { + app.logger.Warn("error registering services", "error", c.err) + } - if err := s.RegisterServices(c); err != nil { - return fmt.Errorf("unable to register services: %w", err) + // merge maps + for path, decoder := range c.queryHandlers { + app.QueryHandlers[path] = decoder + } } - if c.err != nil { - app.logger.Warn("error registering services", "error", c.err) + // if module implements register msg handlers + if module, ok := s.(appmodulev2.HasMsgHandlers); ok { + wrapper := stfRouterWrapper{stfRouter: app.msgRouterBuilder} + module.RegisterMsgHandlers(&wrapper) + if wrapper.error != nil { + return fmt.Errorf("unable to register handlers: %w", wrapper.error) + } } - // merge maps - for path, decoder := range c.grpcQueryDecoders { - app.GRPCMethodsToMessageMap[path] = decoder + // if module implements register query handlers + if module, ok := s.(appmodulev2.HasQueryHandlers); ok { + wrapper := stfRouterWrapper{stfRouter: app.queryRouterBuilder} + module.RegisterQueryHandlers(&wrapper) + + for path, handler := range wrapper.handlers { + app.QueryHandlers[path] = handler + } } return nil @@ -623,9 +663,7 @@ func registerServices[T transaction.Tx](s hasServicesV1, app *App[T], registry * var _ grpc.ServiceRegistrar = (*configurator)(nil) type configurator struct { - // grpcQueryDecoders is required because module expose queries through gRPC - // this provides a way to route to modules using gRPC. - grpcQueryDecoders map[string]func() gogoproto.Message + queryHandlers map[string]appmodulev2.Handler stfQueryRouter *stf.MsgRouterBuilder stfMsgRouter *stf.MsgRouterBuilder @@ -657,28 +695,31 @@ func (c *configurator) RegisterService(sd *grpc.ServiceDesc, ss interface{}) { func (c *configurator) registerQueryHandlers(sd *grpc.ServiceDesc, ss interface{}) error { for _, md := range sd.Methods { // TODO(tip): what if a query is not deterministic? - requestFullName, err := registerMethod(c.stfQueryRouter, sd, md, ss) + + handler, err := grpcHandlerToAppModuleHandler(sd, md, ss) if err != nil { - return fmt.Errorf("unable to register query handler %s.%s: %w", sd.ServiceName, md.MethodName, err) + return fmt.Errorf("unable to make a appmodulev2.HandlerFunc from gRPC handler (%s, %s): %w", sd.ServiceName, md.MethodName, err) } - // register gRPC query method. - typ := gogoproto.MessageType(requestFullName) - if typ == nil { - return fmt.Errorf("unable to find message in gogotype registry: %w", err) - } - decoderFunc := func() gogoproto.Message { - return reflect.New(typ.Elem()).Interface().(gogoproto.Message) + // register to stf query router. + err = c.stfQueryRouter.RegisterHandler(gogoproto.MessageName(handler.MakeMsg()), handler.Func) + if err != nil { + return fmt.Errorf("unable to register handler to stf router (%s, %s): %w", sd.ServiceName, md.MethodName, err) } - methodName := fmt.Sprintf("/%s/%s", sd.ServiceName, md.MethodName) - c.grpcQueryDecoders[methodName] = decoderFunc + + // register query handler using the same mapping used in stf + c.queryHandlers[gogoproto.MessageName(handler.MakeMsg())] = handler } return nil } func (c *configurator) registerMsgHandlers(sd *grpc.ServiceDesc, ss interface{}) error { for _, md := range sd.Methods { - _, err := registerMethod(c.stfMsgRouter, sd, md, ss) + handler, err := grpcHandlerToAppModuleHandler(sd, md, ss) + if err != nil { + return err + } + err = c.stfMsgRouter.RegisterHandler(gogoproto.MessageName(handler.MakeMsg()), handler.Func) if err != nil { return fmt.Errorf("unable to register msg handler %s.%s: %w", sd.ServiceName, md.MethodName, err) } @@ -686,32 +727,27 @@ func (c *configurator) registerMsgHandlers(sd *grpc.ServiceDesc, ss interface{}) return nil } -// requestFullNameFromMethodDesc returns the fully-qualified name of the request message of the provided service's method. -func requestFullNameFromMethodDesc(sd *grpc.ServiceDesc, method grpc.MethodDesc) (protoreflect.FullName, error) { - methodFullName := protoreflect.FullName(fmt.Sprintf("%s.%s", sd.ServiceName, method.MethodName)) - desc, err := gogoproto.HybridResolver.FindDescriptorByName(methodFullName) - if err != nil { - return "", fmt.Errorf("cannot find method descriptor %s", methodFullName) - } - methodDesc, ok := desc.(protoreflect.MethodDescriptor) - if !ok { - return "", fmt.Errorf("invalid method descriptor %s", methodFullName) - } - return methodDesc.Input().FullName(), nil -} - -func registerMethod( - stfRouter *stf.MsgRouterBuilder, +// grpcHandlerToAppModuleHandler converts a gRPC handler into an appmodulev2.HandlerFunc. +func grpcHandlerToAppModuleHandler( sd *grpc.ServiceDesc, md grpc.MethodDesc, ss interface{}, -) (string, error) { - requestName, err := requestFullNameFromMethodDesc(sd, md) +) (appmodulev2.Handler, error) { + requestName, responseName, err := requestFullNameFromMethodDesc(sd, md) if err != nil { - return "", err + return appmodulev2.Handler{}, err + } + + requestTyp := gogoproto.MessageType(string(requestName)) + if requestTyp == nil { + return appmodulev2.Handler{}, fmt.Errorf("no proto message found for %s", requestName) + } + responseTyp := gogoproto.MessageType(string(responseName)) + if responseTyp == nil { + return appmodulev2.Handler{}, fmt.Errorf("no proto message found for %s", responseName) } - return string(requestName), stfRouter.RegisterHandler(string(requestName), func( + handlerFunc := func( ctx context.Context, msg transaction.Msg, ) (resp transaction.Msg, err error) { @@ -720,7 +756,17 @@ func registerMethod( return nil, err } return res.(transaction.Msg), nil - }) + } + + return appmodulev2.Handler{ + Func: handlerFunc, + MakeMsg: func() transaction.Msg { + return reflect.New(requestTyp.Elem()).Interface().(transaction.Msg) + }, + MakeMsgResp: func() transaction.Msg { + return reflect.New(responseTyp.Elem()).Interface().(transaction.Msg) + }, + }, nil } func noopDecoder(_ interface{}) error { return nil } @@ -736,6 +782,20 @@ func messagePassingInterceptor(msg transaction.Msg) grpc.UnaryServerInterceptor } } +// requestFullNameFromMethodDesc returns the fully-qualified name of the request message and response of the provided service's method. +func requestFullNameFromMethodDesc(sd *grpc.ServiceDesc, method grpc.MethodDesc) (protoreflect.FullName, protoreflect.FullName, error) { + methodFullName := protoreflect.FullName(fmt.Sprintf("%s.%s", sd.ServiceName, method.MethodName)) + desc, err := gogoproto.HybridResolver.FindDescriptorByName(methodFullName) + if err != nil { + return "", "", fmt.Errorf("cannot find method descriptor %s", methodFullName) + } + methodDesc, ok := desc.(protoreflect.MethodDescriptor) + if !ok { + return "", "", fmt.Errorf("invalid method descriptor %s", methodFullName) + } + return methodDesc.Input().FullName(), methodDesc.Output().FullName(), nil +} + // defaultMigrationsOrder returns a default migrations order: ascending alphabetical by module name, // except x/auth which will run last, see: // https://github.com/cosmos/cosmos-sdk/issues/10591 @@ -762,3 +822,36 @@ func defaultMigrationsOrder(modules []string) []string { type hasServicesV1 interface { RegisterServices(grpc.ServiceRegistrar) error } + +var _ appmodulev2.MsgRouter = (*stfRouterWrapper)(nil) + +// stfRouterWrapper wraps the stf router and implements the core appmodulev2.MsgRouter +// interface. +// The difference between this type and stf router is that the stf router expects +// us to provide it the msg name, but the core router interface does not have +// such requirement. +type stfRouterWrapper struct { + stfRouter *stf.MsgRouterBuilder + + error error + + handlers map[string]appmodulev2.Handler +} + +func (s *stfRouterWrapper) RegisterHandler(handler appmodulev2.Handler) { + req := handler.MakeMsg() + requestName := gogoproto.MessageName(req) + if requestName == "" { + s.error = errors.Join(s.error, fmt.Errorf("unable to extract request name for type: %T", req)) + } + + // register handler to stf router + err := s.stfRouter.RegisterHandler(requestName, handler.Func) + s.error = errors.Join(s.error, err) + + // also make the decoder + if s.error == nil { + s.handlers = map[string]appmodulev2.Handler{} + } + s.handlers[requestName] = handler +} diff --git a/runtime/v2/module.go b/runtime/v2/module.go index 8db0f557a57b..a95e38f96ea5 100644 --- a/runtime/v2/module.go +++ b/runtime/v2/module.go @@ -16,6 +16,8 @@ import ( reflectionv1 "cosmossdk.io/api/cosmos/reflection/v1" appmodulev2 "cosmossdk.io/core/appmodule/v2" "cosmossdk.io/core/comet" + "cosmossdk.io/core/event" + "cosmossdk.io/core/header" "cosmossdk.io/core/registry" "cosmossdk.io/core/server" "cosmossdk.io/core/store" @@ -25,6 +27,7 @@ import ( "cosmossdk.io/log" "cosmossdk.io/runtime/v2/services" "cosmossdk.io/server/v2/stf" + rootstore "cosmossdk.io/store/v2/root" ) var ( @@ -39,19 +42,19 @@ type appModule[T transaction.Tx] struct { func (m appModule[T]) IsOnePerModuleType() {} func (m appModule[T]) IsAppModule() {} -func (m appModule[T]) RegisterServices(registar grpc.ServiceRegistrar) error { +func (m appModule[T]) RegisterServices(registrar grpc.ServiceRegistrar) error { autoCliQueryService, err := services.NewAutoCLIQueryService(m.app.moduleManager.modules) if err != nil { return err } - autocliv1.RegisterQueryServer(registar, autoCliQueryService) + autocliv1.RegisterQueryServer(registrar, autoCliQueryService) reflectionSvc, err := services.NewReflectionService() if err != nil { return err } - reflectionv1.RegisterReflectionServiceServer(registar, reflectionSvc) + reflectionv1.RegisterReflectionServiceServer(registrar, reflectionSvc) return nil } @@ -96,7 +99,7 @@ func init() { ProvideAppBuilder[transaction.Tx], ProvideEnvironment[transaction.Tx], ProvideModuleManager[transaction.Tx], - ProvideCometService, + ProvideStoreBuilder, ), appconfig.Invoke(SetupAppBuilder), ) @@ -124,13 +127,13 @@ func ProvideAppBuilder[T transaction.Tx]( msgRouterBuilder := stf.NewMsgRouterBuilder() app := &App[T]{ - storeKeys: nil, - interfaceRegistrar: interfaceRegistrar, - amino: amino, - msgRouterBuilder: msgRouterBuilder, - queryRouterBuilder: stf.NewMsgRouterBuilder(), // TODO dedicated query router - GRPCMethodsToMessageMap: map[string]func() proto.Message{}, - storeLoader: DefaultStoreLoader, + storeKeys: nil, + interfaceRegistrar: interfaceRegistrar, + amino: amino, + msgRouterBuilder: msgRouterBuilder, + queryRouterBuilder: stf.NewMsgRouterBuilder(), // TODO dedicated query router + QueryHandlers: map[string]appmodulev2.Handler{}, + storeLoader: DefaultStoreLoader, } appBuilder := &AppBuilder[T]{app: app} @@ -146,7 +149,12 @@ type AppInputs struct { InterfaceRegistrar registry.InterfaceRegistrar LegacyAmino registry.AminoRegistrar Logger log.Logger - DynamicConfig server.DynamicConfig `optional:"true"` // can be nil in client wiring + // StoreBuilder is a builder for a store/v2 RootStore satisfying the Store interface + StoreBuilder *StoreBuilder + // StoreOptions are required as input for the StoreBuilder. If not provided, the default options are used. + StoreOptions *rootstore.Options `optional:"true"` + // DynamicConfig can be nil in client wiring, but is required in server wiring. + DynamicConfig server.DynamicConfig `optional:"true"` } func SetupAppBuilder(inputs AppInputs) { @@ -157,8 +165,22 @@ func SetupAppBuilder(inputs AppInputs) { app.moduleManager.RegisterInterfaces(inputs.InterfaceRegistrar) app.moduleManager.RegisterLegacyAminoCodec(inputs.LegacyAmino) - if inputs.DynamicConfig != nil { - inputs.AppBuilder.config = inputs.DynamicConfig + if inputs.DynamicConfig == nil { + return + } + storeOptions := rootstore.DefaultStoreOptions() + if inputs.StoreOptions != nil { + storeOptions = *inputs.StoreOptions + } + var err error + app.db, err = inputs.StoreBuilder.Build( + inputs.Logger, + app.storeKeys, + inputs.DynamicConfig, + storeOptions, + ) + if err != nil { + panic(err) } } @@ -176,6 +198,9 @@ func ProvideEnvironment[T transaction.Tx]( config *runtimev2.Module, key depinject.ModuleKey, appBuilder *AppBuilder[T], + kvFactory store.KVStoreServiceFactory, + headerService header.Service, + eventService event.Service, ) ( appmodulev2.Environment, store.KVStoreService, @@ -197,7 +222,7 @@ func ProvideEnvironment[T transaction.Tx]( } registerStoreKey(appBuilder, kvStoreKey) - kvService = stf.NewKVStoreService([]byte(kvStoreKey)) + kvService = kvFactory([]byte(kvStoreKey)) memStoreKey := fmt.Sprintf("memory:%s", key.Name()) registerStoreKey(appBuilder, memStoreKey) @@ -207,9 +232,9 @@ func ProvideEnvironment[T transaction.Tx]( env := appmodulev2.Environment{ Logger: logger, BranchService: stf.BranchService{}, - EventService: stf.NewEventService(), + EventService: eventService, GasService: stf.NewGasMeterService(), - HeaderService: stf.HeaderService{}, + HeaderService: headerService, QueryRouterService: stf.NewQueryRouterService(), MsgRouterService: stf.NewMsgRouterService([]byte(key.Name())), TransactionService: services.NewContextAwareTransactionService(), @@ -220,8 +245,8 @@ func ProvideEnvironment[T transaction.Tx]( return env, kvService, memKvService } -func registerStoreKey[T transaction.Tx](wrapper *AppBuilder[T], key string) { - wrapper.app.storeKeys = append(wrapper.app.storeKeys, key) +func registerStoreKey[T transaction.Tx](builder *AppBuilder[T], key string) { + builder.app.storeKeys = append(builder.app.storeKeys, key) } func storeKeyOverride(config *runtimev2.Module, moduleName string) *runtimev2.StoreKeyConfig { @@ -234,6 +259,30 @@ func storeKeyOverride(config *runtimev2.Module, moduleName string) *runtimev2.St return nil } -func ProvideCometService() comet.Service { - return &services.ContextAwareCometInfoService{} +// DefaultServiceBindings provides default services for the following service interfaces: +// - store.KVStoreServiceFactory +// - header.Service +// - comet.Service +// +// They are all required. For most use cases these default services bindings should be sufficient. +// Power users (or tests) may wish to provide their own services bindings, in which case they must +// supply implementations for each of the above interfaces. +func DefaultServiceBindings() depinject.Config { + var ( + kvServiceFactory store.KVStoreServiceFactory = func(actor []byte) store.KVStoreService { + return services.NewGenesisKVService( + actor, + stf.NewKVStoreService(actor), + ) + } + headerService header.Service = services.NewGenesisHeaderService(stf.HeaderService{}) + cometService comet.Service = &services.ContextAwareCometInfoService{} + eventService = stf.NewEventService() + ) + return depinject.Supply( + kvServiceFactory, + headerService, + cometService, + eventService, + ) } diff --git a/runtime/v2/services/genesis.go b/runtime/v2/services/genesis.go new file mode 100644 index 000000000000..79ebd92852f8 --- /dev/null +++ b/runtime/v2/services/genesis.go @@ -0,0 +1,107 @@ +package services + +import ( + "context" + "fmt" + + "cosmossdk.io/core/header" + "cosmossdk.io/core/store" +) + +var ( + _ store.KVStoreService = (*GenesisKVStoreService)(nil) + _ header.Service = (*GenesisHeaderService)(nil) +) + +type genesisContextKeyType struct{} + +var genesisContextKey = genesisContextKeyType{} + +// genesisContext is a context that is used during genesis initialization. +// it backs the store.KVStoreService and header.Service interface implementations +// defined in this file. +type genesisContext struct { + state store.WriterMap +} + +// NewGenesisContext creates a new genesis context. +func NewGenesisContext(state store.WriterMap) genesisContext { + return genesisContext{ + state: state, + } +} + +// Run runs the provided function within the genesis context and returns an +// updated store.WriterMap containing the state modifications made during InitGenesis. +func (g *genesisContext) Run( + ctx context.Context, + fn func(ctx context.Context) error, +) (store.WriterMap, error) { + ctx = context.WithValue(ctx, genesisContextKey, g) + err := fn(ctx) + if err != nil { + return nil, err + } + return g.state, nil +} + +// GenesisKVStoreService is a store.KVStoreService implementation that is used during +// genesis initialization. It wraps an inner execution context store.KVStoreService. +type GenesisKVStoreService struct { + actor []byte + executionService store.KVStoreService +} + +// NewGenesisKVService creates a new GenesisKVStoreService. +// - actor is the module store key. +// - executionService is the store.KVStoreService to use when the genesis context is not active. +func NewGenesisKVService( + actor []byte, + executionService store.KVStoreService, +) *GenesisKVStoreService { + return &GenesisKVStoreService{ + actor: actor, + executionService: executionService, + } +} + +// OpenKVStore implements store.KVStoreService. +func (g *GenesisKVStoreService) OpenKVStore(ctx context.Context) store.KVStore { + v := ctx.Value(genesisContextKey) + if v == nil { + return g.executionService.OpenKVStore(ctx) + } + genCtx, ok := v.(*genesisContext) + if !ok { + panic(fmt.Errorf("unexpected genesis context type: %T", v)) + } + state, err := genCtx.state.GetWriter(g.actor) + if err != nil { + panic(err) + } + return state +} + +// GenesisHeaderService is a header.Service implementation that is used during +// genesis initialization. It wraps an inner execution context header.Service. +type GenesisHeaderService struct { + executionService header.Service +} + +// HeaderInfo implements header.Service. +// During genesis initialization, it returns an empty header.Info. +func (g *GenesisHeaderService) HeaderInfo(ctx context.Context) header.Info { + v := ctx.Value(genesisContextKey) + if v == nil { + return g.executionService.HeaderInfo(ctx) + } + return header.Info{} +} + +// NewGenesisHeaderService creates a new GenesisHeaderService. +// - executionService is the header.Service to use when the genesis context is not active. +func NewGenesisHeaderService(executionService header.Service) *GenesisHeaderService { + return &GenesisHeaderService{ + executionService: executionService, + } +} diff --git a/runtime/v2/store.go b/runtime/v2/store.go index 5268033ad323..6c45dd5e72db 100644 --- a/runtime/v2/store.go +++ b/runtime/v2/store.go @@ -1,12 +1,18 @@ package runtime import ( + "errors" "fmt" + "path/filepath" + "cosmossdk.io/core/server" "cosmossdk.io/core/store" + "cosmossdk.io/log" "cosmossdk.io/server/v2/stf" storev2 "cosmossdk.io/store/v2" + "cosmossdk.io/store/v2/db" "cosmossdk.io/store/v2/proof" + "cosmossdk.io/store/v2/root" ) // NewKVStoreService creates a new KVStoreService. @@ -58,6 +64,58 @@ type Store interface { LastCommitID() (proof.CommitID, error) } +// StoreBuilder is a builder for a store/v2 RootStore satisfying the Store interface. +type StoreBuilder struct { + store Store +} + +// Build creates a new store/v2 RootStore. +func (sb *StoreBuilder) Build( + logger log.Logger, + storeKeys []string, + config server.DynamicConfig, + options root.Options, +) (Store, error) { + if sb.store != nil { + return sb.store, nil + } + home := config.GetString(flagHome) + scRawDb, err := db.NewDB( + db.DBType(config.GetString("store.app-db-backend")), + "application", + filepath.Join(home, "data"), + nil, + ) + if err != nil { + return nil, fmt.Errorf("failed to create SCRawDB: %w", err) + } + + factoryOptions := &root.FactoryOptions{ + Logger: logger, + RootDir: home, + Options: options, + // STF needs to store a bit of state + StoreKeys: append(storeKeys, "stf"), + SCRawDB: scRawDb, + } + + rs, err := root.CreateRootStore(factoryOptions) + if err != nil { + return nil, fmt.Errorf("failed to create root store: %w", err) + } + sb.store = rs + return sb.store, nil +} + +// Get returns the Store. Build must be called before calling Get or the result will be nil. +func (sb *StoreBuilder) Get() Store { + return sb.store +} + +func ProvideStoreBuilder() *StoreBuilder { + return &StoreBuilder{} +} + // StoreLoader allows for custom loading of the store, this is useful when upgrading the store from a previous version type StoreLoader func(store Store) error @@ -69,6 +127,11 @@ func DefaultStoreLoader(store Store) error { // UpgradeStoreLoader upgrades the store if the upgrade height matches the current version, it is used as a replacement // for the DefaultStoreLoader when there are store upgrades func UpgradeStoreLoader(upgradeHeight int64, storeUpgrades *store.StoreUpgrades) StoreLoader { + // sanity checks on store upgrades + if err := checkStoreUpgrade(storeUpgrades); err != nil { + panic(err) + } + return func(store Store) error { latestVersion, err := store.GetLatestVersion() if err != nil { @@ -88,3 +151,40 @@ func UpgradeStoreLoader(upgradeHeight int64, storeUpgrades *store.StoreUpgrades) return DefaultStoreLoader(store) } } + +// checkStoreUpgrade performs sanity checks on the store upgrades +func checkStoreUpgrade(storeUpgrades *store.StoreUpgrades) error { + if storeUpgrades == nil { + return errors.New("store upgrades cannot be nil") + } + + // check for duplicates + addedFilter := make(map[string]struct{}) + deletedFilter := make(map[string]struct{}) + + for _, key := range storeUpgrades.Added { + if _, ok := addedFilter[key]; ok { + return fmt.Errorf("store upgrade has duplicate key %s in added", key) + } + addedFilter[key] = struct{}{} + } + for _, key := range storeUpgrades.Deleted { + if _, ok := deletedFilter[key]; ok { + return fmt.Errorf("store upgrade has duplicate key %s in deleted", key) + } + deletedFilter[key] = struct{}{} + } + + for _, key := range storeUpgrades.Added { + if _, ok := deletedFilter[key]; ok { + return fmt.Errorf("store upgrade has key %s in both added and deleted", key) + } + } + for _, key := range storeUpgrades.Deleted { + if _, ok := addedFilter[key]; ok { + return fmt.Errorf("store upgrade has key %s in both added and deleted", key) + } + } + + return nil +} diff --git a/runtime/v2/store_test.go b/runtime/v2/store_test.go new file mode 100644 index 000000000000..64ad7e9cc274 --- /dev/null +++ b/runtime/v2/store_test.go @@ -0,0 +1,71 @@ +package runtime + +import ( + "testing" + + corestore "cosmossdk.io/core/store" +) + +func TestCheckStoreUpgrade(t *testing.T) { + tests := []struct { + name string + storeUpgrades *corestore.StoreUpgrades + wantErr bool + errMsg string + }{ + { + name: "Nil StoreUpgrades", + storeUpgrades: nil, + wantErr: true, + errMsg: "store upgrades cannot be nil", + }, + { + name: "Valid StoreUpgrades", + storeUpgrades: &corestore.StoreUpgrades{ + Added: []string{"store1", "store2"}, + Deleted: []string{"store3", "store4"}, + }, + wantErr: false, + }, + { + name: "Duplicate key in Added", + storeUpgrades: &corestore.StoreUpgrades{ + Added: []string{"store1", "store2", "store1"}, + Deleted: []string{"store3"}, + }, + wantErr: true, + errMsg: "store upgrade has duplicate key store1 in added", + }, + { + name: "Duplicate key in Deleted", + storeUpgrades: &corestore.StoreUpgrades{ + Added: []string{"store1"}, + Deleted: []string{"store2", "store3", "store2"}, + }, + wantErr: true, + errMsg: "store upgrade has duplicate key store2 in deleted", + }, + { + name: "Key in both Added and Deleted", + storeUpgrades: &corestore.StoreUpgrades{ + Added: []string{"store1", "store2"}, + Deleted: []string{"store2", "store3"}, + }, + wantErr: true, + errMsg: "store upgrade has key store2 in both added and deleted", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + err := checkStoreUpgrade(tt.storeUpgrades) + if (err != nil) != tt.wantErr { + t.Errorf("checkStoreUpgrade() error = %v, wantErr %v", err, tt.wantErr) + return + } + if err != nil && err.Error() != tt.errMsg { + t.Errorf("checkStoreUpgrade() error message = %v, want %v", err.Error(), tt.errMsg) + } + }) + } +} diff --git a/runtime/v2/types.go b/runtime/v2/types.go index baa20182b512..9018af921b1c 100644 --- a/runtime/v2/types.go +++ b/runtime/v2/types.go @@ -14,7 +14,7 @@ import ( const ( ModuleName = "runtime" - FlagHome = "home" + flagHome = "home" ) // validateProtoAnnotations validates that the proto annotations are correct. diff --git a/schema/api.go b/schema/api.go new file mode 100644 index 000000000000..3d8224a9a6d9 --- /dev/null +++ b/schema/api.go @@ -0,0 +1,98 @@ +package schema + +// APIDescriptor is a public versioned descriptor of an API. +// +// An APIDescriptor can be used as a native descriptor of an API's encoding. +// The native binary encoding of API requests and responses is to encode the input and output +// fields using value binary encoding. +// The native JSON encoding would be to encode the fields as a JSON object, canonically +// sorted by field name with no extra whitespace. +// Thus, APIDefinitions have deterministic binary and JSON encodings. +// +// APIDefinitions have a strong definition of compatibility between different versions +// of the same API. +// It is an INCOMPATIBLE change to add new input fields to existing methods or to remove or modify +// existing input or output fields. +// Input fields also cannot reference any unsealed structs, directly or transitively, +// because these types allow adding new fields. +// Adding new input fields to a method introduces the possibility that a newer client +// will send an incomprehensible message to an older server. +// The only safe ways that input field schemas can be extended are by adding +// new values to EnumType's and new cases to OneOfType's. +// It is a COMPATIBLE change to add new methods to an API and to add new output fields +// to existing methods. +// Output fields can reference any sealed or unsealed StructType, directly or transitively. +// +// Existing protobuf APIs could also be mapped into APIDefinitions, and used in the following ways: +// - to produce, user-friendly deterministic JSON +// - to produce a deterministic binary encoding +// - to check for compatibility in a way that is more appropriate to blockchain applications +// - to use any code generators designed to support this spec as an alternative to protobuf +// Also, a standardized way of serializing schema types as protobuf could be defined which +// maps to the original protobuf encoding, so that schemas can be used as an interop +// layer between different less expressive encoding systems. +// +// Existing EVM contract APIs expressed in Solidity could be mapped into APIDefinitions, and +// a mapping of all schema values to ABI encoding could be defined which preserves the +// original ABI encoding. +// +// In this way, we can define an interop layer between contracts in the EVM world, +// SDK modules accepting protobuf types, and any API using this schema system natively. +type APIDescriptor struct { + // Name is the versioned name of the API. + Name string + + // Methods is the list of methods in the API. + // It is a COMPATIBLE change to add new methods to an API. + // If a newer client tries to call a method that an older server does not recognize it, + // an error will simply be returned. + Methods []MethodDescriptor +} + +// MethodDescriptor describes a method in the API. +type MethodDescriptor struct { + // Name is the name of the method. + Name string + + // InputFields is the list of input fields for the method. + // + // It is an INCOMPATIBLE change to add, remove or update input fields to a method. + // The addition of new fields introduces the possibility that a newer client + // will send an incomprehensible message to an older server. + // InputFields can only reference sealed StructTypes, either directly and transitively. + // + // As a special case to represent protobuf service definitions, there can be a single + // unnamed struct input field that code generators can choose to either reference + // as a named struct or to expand inline as function arguments. + InputFields []Field + + // OutputFields is the list of output fields for the method. + // + // It is a COMPATIBLE change to add new output fields to a method, + // but existing output fields should not be removed or modified. + // OutputFields can reference any sealed or unsealed StructType, directly or transitively. + // If a newer client tries to call a method on an older server, the newer expected result output + // fields will simply be populated with the default values for that field kind. + // + // As a special case to represent protobuf service definitions, there can be a single + // unnamed struct output field. + // In this case, adding new output fields is an INCOMPATIBLE change (because protobuf service definitions + // don't allow this), but new fields can be added to the referenced struct if it is unsealed. + OutputFields []Field + + // Volatility is the volatility of the method. + Volatility Volatility +} + +// Volatility is the volatility of a method. +type Volatility int + +const ( + // PureVolatility indicates that the method can neither read nor write state. + PureVolatility Volatility = iota + // ReadonlyVolatility indicates that the method can read state but not write state. + ReadonlyVolatility + + // VolatileVolatility indicates that the method can read and write state. + VolatileVolatility +) diff --git a/schema/appdata/mux.go b/schema/appdata/mux.go index 81a4fa795db8..1eab8b69a6fe 100644 --- a/schema/appdata/mux.go +++ b/schema/appdata/mux.go @@ -139,7 +139,7 @@ func ListenerMux(listeners ...Listener) Listener { mux.onBatch = func(batch PacketBatch) error { for _, listener := range listeners { - err := batch.apply(&listener) + err := batch.apply(&listener) //nolint:gosec // aliasing is safe here if err != nil { return err } diff --git a/schema/decoding/resolver.go b/schema/decoding/resolver.go index cb022dbb6947..5478573401f6 100644 --- a/schema/decoding/resolver.go +++ b/schema/decoding/resolver.go @@ -15,8 +15,8 @@ type DecoderResolver interface { // EncodeModuleName encodes a module name into a byte slice that can be used as the actor in a KVPairUpdate. EncodeModuleName(string) ([]byte, error) - // IterateAll iterates over all available module decoders. - IterateAll(func(moduleName string, cdc schema.ModuleCodec) error) error + // AllDecoders iterates over all available module decoders. + AllDecoders(func(moduleName string, cdc schema.ModuleCodec) error) error // LookupDecoder looks up a specific module decoder. LookupDecoder(moduleName string) (decoder schema.ModuleCodec, found bool, err error) @@ -48,7 +48,7 @@ func (a moduleSetDecoderResolver) EncodeModuleName(s string) ([]byte, error) { return nil, fmt.Errorf("module %s not found", s) } -func (a moduleSetDecoderResolver) IterateAll(f func(string, schema.ModuleCodec) error) error { +func (a moduleSetDecoderResolver) AllDecoders(f func(string, schema.ModuleCodec) error) error { keys := make([]string, 0, len(a.moduleSet)) for k := range a.moduleSet { keys = append(keys, k) diff --git a/schema/decoding/resolver_test.go b/schema/decoding/resolver_test.go index e3a98863681a..2cf13b52b6cf 100644 --- a/schema/decoding/resolver_test.go +++ b/schema/decoding/resolver_test.go @@ -43,7 +43,7 @@ var testResolver = ModuleSetDecoderResolver(moduleSet) func TestModuleSetDecoderResolver_IterateAll(t *testing.T) { objectTypes := map[string]bool{} - err := testResolver.IterateAll(func(moduleName string, cdc schema.ModuleCodec) error { + err := testResolver.AllDecoders(func(moduleName string, cdc schema.ModuleCodec) error { cdc.Schema.AllTypes(func(t schema.Type) bool { objTyp, ok := t.(schema.StateObjectType) if ok { @@ -128,7 +128,7 @@ func TestModuleSetDecoderResolver_IterateAll_Error(t *testing.T) { resolver := ModuleSetDecoderResolver(map[string]interface{}{ "modD": modD{}, }) - err := resolver.IterateAll(func(moduleName string, cdc schema.ModuleCodec) error { + err := resolver.AllDecoders(func(moduleName string, cdc schema.ModuleCodec) error { if moduleName == "modD" { t.Fatalf("expected error") } diff --git a/schema/decoding/sync.go b/schema/decoding/sync.go index d8aee9884c6a..68690b5716c9 100644 --- a/schema/decoding/sync.go +++ b/schema/decoding/sync.go @@ -27,7 +27,7 @@ func Sync(listener appdata.Listener, source SyncSource, resolver DecoderResolver return nil } - return resolver.IterateAll(func(moduleName string, cdc schema.ModuleCodec) error { + return resolver.AllDecoders(func(moduleName string, cdc schema.ModuleCodec) error { if opts.ModuleFilter != nil && !opts.ModuleFilter(moduleName) { // ignore this module return nil diff --git a/schema/diff/diff_test.go b/schema/diff/diff_test.go index 2785afc575e3..6b12c6c2e6cb 100644 --- a/schema/diff/diff_test.go +++ b/schema/diff/diff_test.go @@ -332,6 +332,7 @@ func TestCompareModuleSchemas(t *testing.T) { } func requireModuleSchema(t *testing.T, types ...schema.Type) schema.ModuleSchema { + t.Helper() s, err := schema.CompileModuleSchema(types...) if err != nil { t.Fatal(err) diff --git a/schema/field.go b/schema/field.go index 0d762aa58dc6..b2bc76a2e3b6 100644 --- a/schema/field.go +++ b/schema/field.go @@ -15,8 +15,21 @@ type Field struct { // Nullable indicates whether null values are accepted for the field. Key fields CANNOT be nullable. Nullable bool `json:"nullable,omitempty"` - // ReferencedType is the referenced type name when Kind is EnumKind. + // ReferencedType is the referenced type name when Kind is EnumKind, StructKind or OneOfKind. ReferencedType string `json:"referenced_type,omitempty"` + + // ElementKind is the element type when Kind is ListKind. + // Support for this is currently UNIMPLEMENTED, this notice will be removed when it is added. + ElementKind Kind `json:"element_kind,omitempty"` + + // Size specifies the size or max-size of a field. + // Support for this is currently UNIMPLEMENTED, this notice will be removed when it is added. + // Its specific meaning may vary depending on the field kind. + // For IntNKind and UintNKind fields, it specifies the bit width of the field. + // For StringKind, BytesKind, AddressKind, and JSONKind, fields it specifies the maximum length rather than a fixed length. + // If it is 0, such fields have no maximum length. + // It is invalid to have a non-zero Size for other kinds. + Size uint32 `json:"size,omitempty"` } // Validate validates the field. @@ -75,7 +88,7 @@ func (c Field) ValidateValue(value interface{}, typeSet TypeSet) error { } err := enumType.ValidateValue(value.(string)) if err != nil { - return fmt.Errorf("invalid value for enum field %q: %v", c.Name, err) + return fmt.Errorf("invalid value for enum field %q: %v", c.Name, err) //nolint:errorlint // false positive due to using go1.12 } default: } diff --git a/schema/indexer/README.md b/schema/indexer/README.md index 9fdec6753a27..9892bccea28d 100644 --- a/schema/indexer/README.md +++ b/schema/indexer/README.md @@ -6,7 +6,7 @@ Indexer implementations should be registered with the `indexer.Register` functio # Integrating the Indexer Manager -The indexer manager should be used for managing all indexers and should be integrated directly with applications wishing to support indexing. The `StartManager` function is used to start the manager. The configuration options for the manager and all indexer targets should be passed as the ManagerOptions.Config field and should match the json structure of ManagerConfig. An example configuration section in `app.toml` might look like this: +The indexer manager should be used for managing all indexers and should be integrated directly with applications wishing to support indexing. The `StartIndexing` function is used to start the manager. The configuration options for the manager and all indexer targets should be passed as the ManagerOptions.Config field and should match the json structure of ManagerConfig. An example configuration section in `app.toml` might look like this: ```toml [indexer.target.postgres] diff --git a/schema/indexer/config.go b/schema/indexer/config.go new file mode 100644 index 000000000000..2b2ea13485bd --- /dev/null +++ b/schema/indexer/config.go @@ -0,0 +1,52 @@ +package indexer + +// Config species the configuration passed to an indexer initialization function. +// It includes both common configuration options related to include or excluding +// parts of the data stream as well as indexer specific options under the config +// subsection. +// +// NOTE: it is an error for an indexer to change its common options, such as adding +// or removing indexed modules, after the indexer has been initialized because this +// could result in an inconsistent state. +type Config struct { + // Type is the name of the indexer type as registered with Register. + Type string `mapstructure:"type" toml:"type" json:"type" comment:"The name of the registered indexer type."` + + // Config are the indexer specific config options specified by the user. + Config interface{} `mapstructure:"config" toml:"config" json:"config,omitempty" comment:"Indexer specific configuration options."` + + // Filter is the filter configuration for the indexer. + Filter *FilterConfig `mapstructure:"filter" toml:"filter" json:"filter,omitempty" comment:"Filter configuration for the indexer. Currently UNSUPPORTED!"` +} + +// FilterConfig specifies the configuration for filtering the data stream +type FilterConfig struct { + // ExcludeState specifies that the indexer will not receive state updates. + ExcludeState bool `mapstructure:"exclude_state" toml:"exclude_state" json:"exclude_state" comment:"Exclude all state updates."` + + // ExcludeEvents specifies that the indexer will not receive events. + ExcludeEvents bool `mapstructure:"exclude_events" toml:"exclude_events" json:"exclude_events" comment:"Exclude all events."` + + // ExcludeTxs specifies that the indexer will not receive transaction's. + ExcludeTxs bool `mapstructure:"exclude_txs" toml:"exclude_txs" json:"exclude_txs" comment:"Exclude all transactions."` + + // ExcludeBlockHeaders specifies that the indexer will not receive block headers, + // although it will still receive StartBlock and Commit callbacks, just without + // the header data. + ExcludeBlockHeaders bool `mapstructure:"exclude_block_headers" toml:"exclude_block_headers" json:"exclude_block_headers" comment:"Exclude all block headers."` + + Modules *ModuleFilterConfig `mapstructure:"modules" toml:"modules" json:"modules,omitempty" comment:"Module filter configuration."` +} + +// ModuleFilterConfig specifies the configuration for filtering modules. +type ModuleFilterConfig struct { + // Include specifies a list of modules whose state the indexer will + // receive state updates for. + // Only one of include or exclude modules should be specified. + Include []string `mapstructure:"include" toml:"include" json:"include" comment:"List of modules to include. Only one of include or exclude should be specified."` + + // Exclude specifies a list of modules whose state the indexer will not + // receive state updates for. + // Only one of include or exclude modules should be specified. + Exclude []string `mapstructure:"exclude" toml:"exclude" json:"exclude" comment:"List of modules to exclude. Only one of include or exclude should be specified."` +} diff --git a/schema/indexer/indexer.go b/schema/indexer/indexer.go index 3b82e3254e5a..6954dee082c7 100644 --- a/schema/indexer/indexer.go +++ b/schema/indexer/indexer.go @@ -9,44 +9,13 @@ import ( "cosmossdk.io/schema/view" ) -// Config species the configuration passed to an indexer initialization function. -// It includes both common configuration options related to include or excluding -// parts of the data stream as well as indexer specific options under the config -// subsection. -// -// NOTE: it is an error for an indexer to change its common options, such as adding -// or removing indexed modules, after the indexer has been initialized because this -// could result in an inconsistent state. -type Config struct { - // Type is the name of the indexer type as registered with Register. - Type string `json:"type"` +// Initializer describes an indexer initialization function and other metadata. +type Initializer struct { + // InitFunc is the function that initializes the indexer. + InitFunc InitFunc - // Config are the indexer specific config options specified by the user. - Config map[string]interface{} `json:"config"` - - // ExcludeState specifies that the indexer will not receive state updates. - ExcludeState bool `json:"exclude_state"` - - // ExcludeEvents specifies that the indexer will not receive events. - ExcludeEvents bool `json:"exclude_events"` - - // ExcludeTxs specifies that the indexer will not receive transaction's. - ExcludeTxs bool `json:"exclude_txs"` - - // ExcludeBlockHeaders specifies that the indexer will not receive block headers, - // although it will still receive StartBlock and Commit callbacks, just without - // the header data. - ExcludeBlockHeaders bool `json:"exclude_block_headers"` - - // IncludeModules specifies a list of modules whose state the indexer will - // receive state updates for. - // Only one of include or exclude modules should be specified. - IncludeModules []string `json:"include_modules"` - - // ExcludeModules specifies a list of modules whose state the indexer will not - // receive state updates for. - // Only one of include or exclude modules should be specified. - ExcludeModules []string `json:"exclude_modules"` + // ConfigType is the type of the configuration object that the indexer expects. + ConfigType interface{} } type InitFunc = func(InitParams) (InitResult, error) diff --git a/schema/indexer/manager.go b/schema/indexer/manager.go deleted file mode 100644 index 60c19b4dd5c7..000000000000 --- a/schema/indexer/manager.go +++ /dev/null @@ -1,50 +0,0 @@ -package indexer - -import ( - "context" - - "cosmossdk.io/schema/addressutil" - "cosmossdk.io/schema/appdata" - "cosmossdk.io/schema/decoding" - "cosmossdk.io/schema/logutil" -) - -// ManagerOptions are the options for starting the indexer manager. -type ManagerOptions struct { - // Config is the user configuration for all indexing. It should generally be an instance of map[string]interface{} - // and match the json structure of ManagerConfig. The manager will attempt to convert it to ManagerConfig. - Config interface{} - - // Resolver is the decoder resolver that will be used to decode the data. It is required. - Resolver decoding.DecoderResolver - - // SyncSource is a representation of the current state of key-value data to be used in a catch-up sync. - // Catch-up syncs will be performed at initialization when necessary. SyncSource is optional but if - // it is omitted, indexers will only be able to start indexing state from genesis. - SyncSource decoding.SyncSource - - // Logger is the logger that indexers can use to write logs. It is optional. - Logger logutil.Logger - - // Context is the context that indexers should use for shutdown signals via Context.Done(). It can also - // be used to pass down other parameters to indexers if necessary. If it is omitted, context.Background - // will be used. - Context context.Context - - // AddressCodec is the address codec that indexers can use to encode and decode addresses. It should always be - // provided, but if it is omitted, the indexer manager will use a default codec which encodes and decodes addresses - // as hex strings. - AddressCodec addressutil.AddressCodec -} - -// ManagerConfig is the configuration of the indexer manager and contains the configuration for each indexer target. -type ManagerConfig struct { - // Target is a map of named indexer targets to their configuration. - Target map[string]Config -} - -// StartManager starts the indexer manager with the given options. The state machine should write all relevant app data to -// the returned listener. -func StartManager(opts ManagerOptions) (appdata.Listener, error) { - panic("TODO: this will be implemented in a follow-up PR, this function is just a stub to demonstrate the API") -} diff --git a/schema/indexer/registry.go b/schema/indexer/registry.go index 445f56876add..0345ed6ad7ef 100644 --- a/schema/indexer/registry.go +++ b/schema/indexer/registry.go @@ -3,12 +3,16 @@ package indexer import "fmt" // Register registers an indexer type with the given initialization function. -func Register(indexerType string, initFunc InitFunc) { +func Register(indexerType string, descriptor Initializer) { if _, ok := indexerRegistry[indexerType]; ok { panic(fmt.Sprintf("indexer %s already registered", indexerType)) } - indexerRegistry[indexerType] = initFunc + if descriptor.InitFunc == nil { + panic(fmt.Sprintf("indexer %s has no initialization function", indexerType)) + } + + indexerRegistry[indexerType] = descriptor } -var indexerRegistry = map[string]InitFunc{} +var indexerRegistry = map[string]Initializer{} diff --git a/schema/indexer/registry_test.go b/schema/indexer/registry_test.go index b9f46910c8fd..0cd26b9629d5 100644 --- a/schema/indexer/registry_test.go +++ b/schema/indexer/registry_test.go @@ -3,15 +3,17 @@ package indexer import "testing" func TestRegister(t *testing.T) { - Register("test", func(params InitParams) (InitResult, error) { - return InitResult{}, nil + Register("test", Initializer{ + InitFunc: func(params InitParams) (InitResult, error) { + return InitResult{}, nil + }, }) - if indexerRegistry["test"] == nil { + if _, ok := indexerRegistry["test"]; !ok { t.Fatalf("expected to find indexer") } - if indexerRegistry["test2"] != nil { + if _, ok := indexerRegistry["test2"]; ok { t.Fatalf("expected not to find indexer") } @@ -20,7 +22,9 @@ func TestRegister(t *testing.T) { t.Fatalf("expected to panic") } }() - Register("test", func(params InitParams) (InitResult, error) { - return InitResult{}, nil + Register("test", Initializer{ + InitFunc: func(params InitParams) (InitResult, error) { + return InitResult{}, nil + }, }) } diff --git a/schema/indexer/start.go b/schema/indexer/start.go new file mode 100644 index 000000000000..909db71ed61a --- /dev/null +++ b/schema/indexer/start.go @@ -0,0 +1,212 @@ +package indexer + +import ( + "context" + "encoding/json" + "fmt" + "reflect" + "sync" + + "cosmossdk.io/schema/addressutil" + "cosmossdk.io/schema/appdata" + "cosmossdk.io/schema/decoding" + "cosmossdk.io/schema/logutil" + "cosmossdk.io/schema/view" +) + +// IndexingOptions are the options for starting the indexer manager. +type IndexingOptions struct { + // Config is the user configuration for all indexing. It should generally be an instance map[string]interface{} + // or json.RawMessage and match the json structure of IndexingConfig, or it can be an instance of IndexingConfig. + // The manager will attempt to convert it to IndexingConfig. + Config interface{} + + // Resolver is the decoder resolver that will be used to decode the data. It is required. + Resolver decoding.DecoderResolver + + // SyncSource is a representation of the current state of key-value data to be used in a catch-up sync. + // Catch-up syncs will be performed at initialization when necessary. SyncSource is optional but if + // it is omitted, indexers will only be able to start indexing state from genesis. + SyncSource decoding.SyncSource + + // Logger is the logger that indexers can use to write logs. It is optional. + Logger logutil.Logger + + // Context is the context that indexers should use for shutdown signals via Context.Done(). It can also + // be used to pass down other parameters to indexers if necessary. If it is omitted, context.Background + // will be used. + Context context.Context + + // AddressCodec is the address codec that indexers can use to encode and decode addresses. It should always be + // provided, but if it is omitted, the indexer manager will use a default codec which encodes and decodes addresses + // as hex strings. + AddressCodec addressutil.AddressCodec + + // DoneWaitGroup is a wait group that all indexer manager go routines will wait on before returning when the context + // is done. + // It is optional. + DoneWaitGroup *sync.WaitGroup +} + +// IndexingConfig is the configuration of the indexer manager and contains the configuration for each indexer target. +type IndexingConfig struct { + // Target is a map of named indexer targets to their configuration. + Target map[string]Config + + // ChannelBufferSize is the buffer size of the channels used for buffering data sent to indexer go routines. + // It defaults to 1024. + ChannelBufferSize *int `json:"channel_buffer_size,omitempty"` +} + +// IndexingTarget returns the indexing target listener and associated data. +// The returned listener is the root listener to which app data should be sent. +type IndexingTarget struct { + // Listener is the root listener to which app data should be sent. + // It will do all processing in the background so updates should be sent synchronously. + Listener appdata.Listener + + // ModuleFilter returns the root module filter which an app can use to exclude modules at the storage level, + // if such a filter is set. + ModuleFilter *ModuleFilterConfig + + IndexerInfos map[string]IndexerInfo +} + +// IndexerInfo contains data returned by a specific indexer after initialization that maybe useful for the app. +type IndexerInfo struct { + // View is the view returned by the indexer in its InitResult. It is optional and may be nil. + View view.AppData +} + +// StartIndexing starts the indexer manager with the given options. The state machine should write all relevant app data to +// the returned listener. +func StartIndexing(opts IndexingOptions) (IndexingTarget, error) { + logger := opts.Logger + if logger == nil { + logger = logutil.NoopLogger{} + } + + logger.Info("Starting indexing") + + cfg, err := unmarshalIndexingConfig(opts.Config) + if err != nil { + return IndexingTarget{}, err + } + + ctx := opts.Context + if ctx == nil { + ctx = context.Background() + } + + listeners := make([]appdata.Listener, 0, len(cfg.Target)) + indexerInfos := make(map[string]IndexerInfo, len(cfg.Target)) + + for targetName, targetCfg := range cfg.Target { + init, ok := indexerRegistry[targetCfg.Type] + if !ok { + return IndexingTarget{}, fmt.Errorf("indexer type %q not found", targetCfg.Type) + } + + logger.Info("Starting indexer", "target_name", targetName, "type", targetCfg.Type) + + if targetCfg.Filter != nil { + return IndexingTarget{}, fmt.Errorf("indexer filter options are not supported yet") + } + + childLogger := logger + if scopeableLogger, ok := logger.(logutil.ScopeableLogger); ok { + childLogger = scopeableLogger.WithContext("indexer", targetName).(logutil.Logger) + } + + targetCfg.Config, err = unmarshalIndexerCustomConfig(targetCfg.Config, init.ConfigType) + if err != nil { + return IndexingTarget{}, fmt.Errorf("failed to unmarshal indexer config for target %q: %v", targetName, err) + } + + initRes, err := init.InitFunc(InitParams{ + Config: targetCfg, + Context: ctx, + Logger: childLogger, + AddressCodec: opts.AddressCodec, + }) + if err != nil { + return IndexingTarget{}, err + } + + listener := initRes.Listener + listeners = append(listeners, listener) + + indexerInfos[targetName] = IndexerInfo{ + View: initRes.View, + } + } + + bufSize := 1024 + if cfg.ChannelBufferSize != nil { + bufSize = *cfg.ChannelBufferSize + } + asyncOpts := appdata.AsyncListenerOptions{ + Context: ctx, + DoneWaitGroup: opts.DoneWaitGroup, + BufferSize: bufSize, + } + + rootListener := appdata.AsyncListenerMux( + asyncOpts, + listeners..., + ) + + rootListener, err = decoding.Middleware(rootListener, opts.Resolver, decoding.MiddlewareOptions{}) + if err != nil { + return IndexingTarget{}, err + } + rootListener = appdata.AsyncListener(asyncOpts, rootListener) + + return IndexingTarget{ + Listener: rootListener, + IndexerInfos: indexerInfos, + }, nil +} + +func unmarshalIndexingConfig(cfg interface{}) (*IndexingConfig, error) { + if x, ok := cfg.(*IndexingConfig); ok { + return x, nil + } + if x, ok := cfg.(IndexingConfig); ok { + return &x, nil + } + + var jsonBz []byte + var err error + + switch cfg := cfg.(type) { + case map[string]interface{}: + jsonBz, err = json.Marshal(cfg) + if err != nil { + return nil, err + } + case json.RawMessage: + jsonBz = cfg + default: + return nil, fmt.Errorf("can't convert %T to %T", cfg, IndexingConfig{}) + } + + var res IndexingConfig + err = json.Unmarshal(jsonBz, &res) + return &res, err +} + +func unmarshalIndexerCustomConfig(cfg, expectedType interface{}) (interface{}, error) { + typ := reflect.TypeOf(expectedType) + if reflect.TypeOf(cfg).AssignableTo(typ) { + return cfg, nil + } + + res := reflect.New(typ).Interface() + bz, err := json.Marshal(cfg) + if err != nil { + return nil, err + } + err = json.Unmarshal(bz, res) + return reflect.ValueOf(res).Elem().Interface(), err +} diff --git a/schema/indexer/start_test.go b/schema/indexer/start_test.go new file mode 100644 index 000000000000..f586af435420 --- /dev/null +++ b/schema/indexer/start_test.go @@ -0,0 +1,220 @@ +package indexer + +import ( + "context" + "encoding/json" + "reflect" + "sync" + "testing" + + "cosmossdk.io/schema/appdata" +) + +func TestStart(t *testing.T) { + ctx, cancelFn := context.WithCancel(context.Background()) + var test1CommitCalled, test2CommitCalled int + Register("test1", Initializer{ + InitFunc: func(params InitParams) (InitResult, error) { + if params.Config.Config.(testConfig).SomeParam != "foobar" { + t.Fatalf("expected %q, got %q", "foobar", params.Config.Config.(testConfig).SomeParam) + } + return InitResult{ + Listener: appdata.Listener{ + Commit: func(data appdata.CommitData) (completionCallback func() error, err error) { + test1CommitCalled++ + return nil, nil + }, + }, + }, nil + }, + ConfigType: testConfig{}, + }) + Register("test2", Initializer{ + InitFunc: func(params InitParams) (InitResult, error) { + if params.Config.Config.(testConfig2).Foo != "bar" { + t.Fatalf("expected %q, got %q", "bar", params.Config.Config.(testConfig2).Foo) + } + return InitResult{ + Listener: appdata.Listener{ + Commit: func(data appdata.CommitData) (completionCallback func() error, err error) { + test2CommitCalled++ + return nil, nil + }, + }, + }, nil + }, + ConfigType: testConfig2{}, + }) + + var wg sync.WaitGroup + target, err := StartIndexing(IndexingOptions{ + Config: IndexingConfig{Target: map[string]Config{ + "t1": {Type: "test1", Config: testConfig{SomeParam: "foobar"}}, + "t2": {Type: "test2", Config: testConfig2{Foo: "bar"}}, + }}, + Resolver: nil, + SyncSource: nil, + Logger: nil, + Context: ctx, + AddressCodec: nil, + DoneWaitGroup: &wg, + }) + if err != nil { + t.Fatal(err) + } + + const COMMIT_COUNT = 10 + for i := 0; i < COMMIT_COUNT; i++ { + callCommit(t, target.Listener) + } + + cancelFn() + wg.Wait() + + if test1CommitCalled != COMMIT_COUNT { + t.Fatalf("expected %d, got %d", COMMIT_COUNT, test1CommitCalled) + } + if test2CommitCalled != COMMIT_COUNT { + t.Fatalf("expected %d, got %d", COMMIT_COUNT, test2CommitCalled) + } +} + +func callCommit(t *testing.T, listener appdata.Listener) { + t.Helper() + cb, err := listener.Commit(appdata.CommitData{}) + if err != nil { + t.Fatal(err) + } + if cb != nil { + err = cb() + if err != nil { + t.Fatal(err) + } + } +} + +func TestUnmarshalIndexingConfig(t *testing.T) { + cfg := &IndexingConfig{Target: map[string]Config{"target": {Type: "type"}}} + jsonBz, err := json.Marshal(cfg) + if err != nil { + t.Fatal(err) + } + + t.Run("json", func(t *testing.T) { + res, err := unmarshalIndexingConfig(json.RawMessage(jsonBz)) + if err != nil { + t.Fatal(err) + } + if !reflect.DeepEqual(res, cfg) { + t.Fatalf("expected %v, got %v", cfg, res) + } + }) + + t.Run("map", func(t *testing.T) { + var m map[string]interface{} + err := json.Unmarshal(jsonBz, &m) + if err != nil { + t.Fatal(err) + } + + res, err := unmarshalIndexingConfig(m) + if err != nil { + t.Fatal(err) + } + if !reflect.DeepEqual(res, cfg) { + t.Fatalf("expected %v, got %v", cfg, res) + } + }) + + t.Run("ptr", func(t *testing.T) { + res, err := unmarshalIndexingConfig(cfg) + if err != nil { + t.Fatal(err) + } + if res != cfg { + t.Fatalf("expected %v, got %v", cfg, res) + } + }) + + t.Run("struct", func(t *testing.T) { + res, err := unmarshalIndexingConfig(*cfg) + if err != nil { + t.Fatal(err) + } + if !reflect.DeepEqual(res, cfg) { + t.Fatalf("expected %v, got %v", cfg, res) + } + }) +} + +func TestUnmarshalIndexerConfig(t *testing.T) { + t.Run("struct", func(t *testing.T) { + cfg := testConfig{SomeParam: "foobar"} + cfg2, err := unmarshalIndexerCustomConfig(cfg, testConfig{}) + if err != nil { + t.Fatal(err) + } + if !reflect.DeepEqual(cfg, cfg2) { + t.Fatalf("expected %v, got %v", cfg, cfg2) + } + }) + + t.Run("ptr", func(t *testing.T) { + cfg := &testConfig{SomeParam: "foobar"} + cfg2, err := unmarshalIndexerCustomConfig(cfg, &testConfig{}) + if err != nil { + t.Fatal(err) + } + if !reflect.DeepEqual(cfg, cfg2) { + t.Fatalf("expected %v, got %v", cfg, cfg2) + } + }) + + t.Run("map -> struct", func(t *testing.T) { + cfg := testConfig{SomeParam: "foobar"} + jzonBz, err := json.Marshal(cfg) + if err != nil { + t.Fatal(err) + } + var m map[string]interface{} + err = json.Unmarshal(jzonBz, &m) + if err != nil { + t.Fatal(err) + } + cfg2, err := unmarshalIndexerCustomConfig(m, testConfig{}) + if err != nil { + t.Fatal(err) + } + if !reflect.DeepEqual(cfg, cfg2) { + t.Fatalf("expected %v, got %v", cfg, cfg2) + } + }) + + t.Run("map -> ptr", func(t *testing.T) { + cfg := &testConfig{SomeParam: "foobar"} + jzonBz, err := json.Marshal(cfg) + if err != nil { + t.Fatal(err) + } + var m map[string]interface{} + err = json.Unmarshal(jzonBz, &m) + if err != nil { + t.Fatal(err) + } + cfg2, err := unmarshalIndexerCustomConfig(m, &testConfig{}) + if err != nil { + t.Fatal(err) + } + if !reflect.DeepEqual(cfg, cfg2) { + t.Fatalf("expected %v, got %v", cfg, cfg2) + } + }) +} + +type testConfig struct { + SomeParam string `json:"some_param"` +} + +type testConfig2 struct { + Foo string `json:"foo"` +} diff --git a/schema/kind.go b/schema/kind.go index 5eedee68c244..0992b297baa7 100644 --- a/schema/kind.go +++ b/schema/kind.go @@ -10,12 +10,25 @@ import ( // Kind represents the basic type of a field in an object. // Each kind defines the following encodings: -// Go Encoding: the golang type which should be accepted by listeners and +// +// - Go Encoding: the golang type which should be accepted by listeners and // generated by decoders when providing entity updates. -// JSON Encoding: the JSON encoding which should be used when encoding the field to JSON. +// - JSON Encoding: the JSON encoding which should be used when encoding the field to JSON. +// - Key Binary Encoding: the encoding which should be used when encoding the field +// as a key in binary messages. Some encodings specify a terminal and non-terminal form +// depending on whether or not the field is the last field in the key. +// - Value Binary Encoding: the encoding which should be used when encoding the field +// as a value in binary messages. +// // When there is some non-determinism in an encoding, kinds should specify what // values they accept and also what is the canonical, deterministic encoding which // should be preferably emitted by serializers. +// +// Binary encodings were chosen based on what is likely to be the most convenient default binary encoding +// for state management implementations. This encoding allows for sorted keys whenever it is possible for a kind +// and is deterministic. +// Modules that use the specified encoding natively will have a trivial decoder implementation because the +// encoding is already in the correct format after any initial prefix bytes are stripped. type Kind int const ( @@ -25,54 +38,82 @@ const ( // StringKind is a string type. // Go Encoding: UTF-8 string with no null characters. // JSON Encoding: string + // Key Binary Encoding: + // non-terminal: UTF-8 string with no null characters suffixed with a null character + // terminal: UTF-8 string with no null characters + // Value Binary Encoding: the same value binary encoding as BytesKind. StringKind - // BytesKind is a bytes type. + // BytesKind represents a byte array. // Go Encoding: []byte // JSON Encoding: base64 encoded string, canonical values should be encoded with standard encoding and padding. // Either standard or URL encoding with or without padding should be accepted. + // Key Binary Encoding: + // non-terminal: length prefixed bytes where the width of the length prefix is 1, 2, 3 or 4 bytes depending on + // the field's MaxLength (defaulting to 4 bytes). + // Length prefixes should be big-endian encoded. + // Values larger than 2^32 bytes are not supported (likely key-value stores impose a lower limit). + // terminal: raw bytes with no length prefix + // Value Binary Encoding: two 32-bit unsigned little-endian integers, the first one representing the offset of the + // value in the buffer and the second one representing the length of the value. BytesKind // Int8Kind represents an 8-bit signed integer. // Go Encoding: int8 // JSON Encoding: number + // Key Binary Encoding: 1-byte two's complement encoding, with the first bit inverted for sorting. + // Value Binary Encoding: 1-byte two's complement encoding. Int8Kind // Uint8Kind represents an 8-bit unsigned integer. // Go Encoding: uint8 // JSON Encoding: number + // Key Binary Encoding: 1-byte unsigned encoding. + // Value Binary Encoding: 1-byte unsigned encoding. Uint8Kind // Int16Kind represents a 16-bit signed integer. // Go Encoding: int16 // JSON Encoding: number + // Key Binary Encoding: 2-byte two's complement big-endian encoding, with the first bit inverted for sorting. + // Value Binary Encoding: 2 byte two's complement little-endian encoding. Int16Kind // Uint16Kind represents a 16-bit unsigned integer. // Go Encoding: uint16 // JSON Encoding: number + // Key Binary Encoding: 2-byte unsigned big-endian encoding. + // Value Binary Encoding: 2-byte unsigned little-endian encoding. Uint16Kind // Int32Kind represents a 32-bit signed integer. // Go Encoding: int32 // JSON Encoding: number + // Key Binary Encoding: 4-byte two's complement big-endian encoding, with the first bit inverted for sorting. + // Value Binary Encoding: 4-byte two's complement little-endian encoding. Int32Kind // Uint32Kind represents a 32-bit unsigned integer. // Go Encoding: uint32 // JSON Encoding: number + // Key Binary Encoding: 4-byte unsigned big-endian encoding. + // Value Binary Encoding: 4-byte unsigned little-endian encoding. Uint32Kind // Int64Kind represents a 64-bit signed integer. // Go Encoding: int64 // JSON Encoding: base10 integer string which matches the IntegerFormat regex // The canonical encoding should include no leading zeros. + // Key Binary Encoding: 8-byte two's complement big-endian encoding, with the first bit inverted for sorting. + // Value Binary Encoding: 8-byte two's complement little-endian encoding. Int64Kind // Uint64Kind represents a 64-bit unsigned integer. // Go Encoding: uint64 // JSON Encoding: base10 integer string which matches the IntegerFormat regex // Canonically encoded values should include no leading zeros. + // Key Binary Encoding: 8-byte unsigned big-endian encoding. + // Value Binary Encoding: 8-byte unsigned little-endian encoding. Uint64Kind // IntegerKind represents an arbitrary precision integer number. @@ -98,6 +139,8 @@ const ( // BoolKind represents a boolean true or false value. // Go Encoding: bool // JSON Encoding: boolean + // Key Binary Encoding: 1-byte encoding where 0 is false and 1 is true. + // Value Binary Encoding: 1-byte encoding where 0 is false and 1 is true. BoolKind // TimeKind represents a nanosecond precision UNIX time value (with zero representing January 1, 1970 UTC). @@ -107,6 +150,8 @@ const ( // Canonical values should be encoded with UTC time zone Z, nanoseconds should // be encoded with no trailing zeros, and T time values should always be present // even at 00:00:00. + // Key Binary Encoding: 8-byte two's complement big-endian encoding, with the first bit inverted for sorting. + // Value Binary Encoding: 8-byte two's complement little-endian encoding. TimeKind // DurationKind represents the elapsed time between two nanosecond precision time values. @@ -114,24 +159,35 @@ const ( // Go Encoding: time.Duration // JSON Encoding: the number of seconds as a decimal string with no trailing zeros followed by // a lowercase 's' character to represent seconds. + // Key Binary Encoding: 8-byte two's complement big-endian encoding, with the first bit inverted for sorting. + // Value Binary Encoding: 8-byte two's complement little-endian encoding. DurationKind // Float32Kind represents an IEEE-754 32-bit floating point number. // Go Encoding: float32 // JSON Encoding: number + // Key Binary Encoding: 4-byte IEEE-754 encoding. + // Value Binary Encoding: 4-byte IEEE-754 encoding. Float32Kind // Float64Kind represents an IEEE-754 64-bit floating point number. // Go Encoding: float64 // JSON Encoding: number + // Key Binary Encoding: 8-byte IEEE-754 encoding. + // Value Binary Encoding: 8-byte IEEE-754 encoding. Float64Kind // AddressKind represents an account address which is represented by a variable length array of bytes. // Addresses usually have a human-readable rendering, such as bech32, and tooling should provide - // a way for apps to define a string encoder for friendly user-facing display. + // a way for apps to define a string encoder for friendly user-facing display. Addresses have a maximum + // supported length of 63 bytes. // Go Encoding: []byte // JSON Encoding: addresses should be encoded as strings using the human-readable address renderer // provided to the JSON encoder. + // Key Binary Encoding: + // non-terminal: bytes prefixed with 1-byte length prefix + // terminal: raw bytes with no length prefix + // Value Binary Encoding: bytes prefixed with 1-byte length prefix. AddressKind // EnumKind represents a value of an enum type. @@ -139,12 +195,68 @@ const ( // definition. // Go Encoding: string // JSON Encoding: string + // Key Binary Encoding: the same binary encoding as the EnumType's numeric kind. + // Value Binary Encoding: the same binary encoding as the EnumType's numeric kind. EnumKind // JSONKind represents arbitrary JSON data. // Go Encoding: json.RawMessage // JSON Encoding: any valid JSON value + // Key Binary Encoding: string encoding + // Value Binary Encoding: string encoding JSONKind + + // UIntNKind represents a signed integer type with a width in bits specified by the Size field in the + // field definition. + // Support for this is currently UNIMPLEMENTED, this notice will be removed when it is added. + // N must be a multiple of 8, and it is invalid for N to equal 8, 16, 32, 64 as there are more specific + // types for these widths. + // Go Encoding: []byte where len([]byte) == Size / 8, little-endian encoded. + // JSON Encoding: base10 integer string matching the IntegerFormat regex, canonically with no leading zeros. + // Key Binary Encoding: N / 8 bytes big-endian encoded + // Value Binary Encoding: N / 8 bytes little-endian encoded + UIntNKind + + // IntNKind represents an unsigned integer type with a width in bits specified by the Size field in the + // field definition. N must be a multiple of 8. + // Support for this is currently UNIMPLEMENTED, this notice will be removed when it is added. + // N must be a multiple of 8, and it is invalid for N to equal 8, 16, 32, 64 as there are more specific + // types for these widths. + // Go Encoding: []byte where len([]byte) == Size / 8, two's complement little-endian encoded. + // JSON Encoding: base10 integer string matching the IntegerFormat regex, canonically with no leading zeros. + // Key Binary Encoding: N / 8 bytes big-endian two's complement encoded with the first bit inverted for sorting. + // Value Binary Encoding: N / 8 bytes little-endian two's complement encoded. + IntNKind + + // StructKind represents a struct object. + // Support for this is currently UNIMPLEMENTED, this notice will be removed when it is added. + // Go Encoding: an array of type []interface{} where each element is of the respective field's kind type. + // JSON Encoding: an object where each key is the field name and the value is the field value. + // Canonically, keys are in alphabetical order with no extra whitespace. + // Key Binary Encoding: not valid as a key field. + // Value Binary Encoding: 32-bit unsigned little-endian length prefix, + // followed by the value binary encoding of each field in order. + StructKind + + // OneOfKind represents a field that can be one of a set of types. + // Support for this is currently UNIMPLEMENTED, this notice will be removed when it is added. + // Go Encoding: the anonymous struct { Case string; Value interface{} }, aliased as OneOfValue. + // JSON Encoding: same as the case's struct encoding with "@type" set to the case name. + // Key Binary Encoding: not valid as a key field. + // Value Binary Encoding: the oneof's discriminant numeric value encoded as its discriminant kind + // followed by the encoded value. + OneOfKind + + // ListKind represents a list of elements. + // Support for this is currently UNIMPLEMENTED, this notice will be removed when it is added. + // Go Encoding: an array of type []interface{} where each element is of the respective field's kind type. + // JSON Encoding: an array of values where each element is the field value. + // Canonically, there is no extra whitespace. + // Key Binary Encoding: not valid as a key field. + // Value Binary Encoding: 32-bit unsigned little-endian size prefix indicating the size of the encoded data in bytes, + // followed by a 32-bit unsigned little-endian count of the number of elements in the list, + // followed by each element encoded with value binary encoding. + ListKind ) // MAX_VALID_KIND is the maximum valid kind value. diff --git a/schema/logutil/logger.go b/schema/logutil/logger.go index cb6b34ebfd2b..a93b91567df2 100644 --- a/schema/logutil/logger.go +++ b/schema/logutil/logger.go @@ -21,6 +21,13 @@ type Logger interface { Debug(msg string, keyVals ...interface{}) } +// ScopeableLogger is a logger that can be scoped with key/value pairs. +// It is implemented by all the loggers in cosmossdk.io/log. +type ScopeableLogger interface { + // WithContext returns a new logger with the provided key/value pairs set. + WithContext(keyVals ...interface{}) interface{} +} + // NoopLogger is a logger that doesn't do anything. type NoopLogger struct{} diff --git a/schema/oneof.go b/schema/oneof.go new file mode 100644 index 000000000000..ec0cd6d649ae --- /dev/null +++ b/schema/oneof.go @@ -0,0 +1,43 @@ +package schema + +// OneOfType represents a oneof type. +// Support for this is currently UNIMPLEMENTED, this notice will be removed when it is added. +type OneOfType struct { + // Name is the name of the oneof type. It must conform to the NameFormat regular expression. + Name string + + // Cases is a list of cases in the oneof type. + // It is a COMPATIBLE change to add new cases to a oneof type. + // If a newer client tries to send a message with a case that an older server does not recognize, + // the older server will simply reject it in a switch statement. + // It is INCOMPATIBLE to remove existing cases from a oneof type. + Cases []OneOfCase + + // DiscriminantKind is the kind of the discriminant field. + // It must be Uint8Kind, Int8Kind, Uint16Kind, Int16Kind, or Int32Kind. + DiscriminantKind Kind +} + +// OneOfCase represents a case in a oneof type. It is represented by a struct type internally with a discriminant value. +type OneOfCase struct { + // Name is the name of the case. It must conform to the NameFormat regular expression. + Name string + + // Discriminant is the discriminant value for the case. + Discriminant int32 + + // Kind is the kind of the case. ListKind is not allowed. + Kind Kind + + // Reference is the referenced type if Kind is EnumKind, StructKind, or OneOfKind. + ReferencedType string +} + +// OneOfValue is the golang runtime representation of a oneof value. +type OneOfValue = struct { + // Case is the name of the case. + Case string + + // Value is the value of the case. + Value interface{} +} diff --git a/schema/state_object.go b/schema/state_object.go index a4825726f685..eff8d1f98459 100644 --- a/schema/state_object.go +++ b/schema/state_object.go @@ -9,16 +9,23 @@ type StateObjectType struct { Name string `json:"name"` // KeyFields is a list of fields that make up the primary key of the object. - // It can be empty in which case indexers should assume that this object is + // It can be empty, in which case, indexers should assume that this object is // a singleton and only has one value. Field names must be unique within the // object between both key and value fields. - // Key fields CANNOT be nullable and Float32Kind, Float64Kind, and JSONKind types - // are not allowed. + // Key fields CANNOT be nullable and Float32Kind, Float64Kind, JSONKind, StructKind, + // OneOfKind, RepeatedKind, ListKind or ObjectKind + // are NOT ALLOWED. + // It is an INCOMPATIBLE change to add, remove or change fields in the key as this + // changes the underlying primary key of the object. KeyFields []Field `json:"key_fields,omitempty"` // ValueFields is a list of fields that are not part of the primary key of the object. // It can be empty in the case where all fields are part of the primary key. // Field names must be unique within the object between both key and value fields. + // ObjectKind fields are not allowed. + // It is a COMPATIBLE change to add new value fields to an object type because + // this does not affect the primary key of the object. + // Existing value fields should not be removed or modified. ValueFields []Field `json:"value_fields,omitempty"` // RetainDeletions is a flag that indicates whether the indexer should retain diff --git a/schema/struct.go b/schema/struct.go new file mode 100644 index 000000000000..20676a743ade --- /dev/null +++ b/schema/struct.go @@ -0,0 +1,21 @@ +package schema + +// StructType represents a struct type. +// Support for this is currently UNIMPLEMENTED, this notice will be removed when it is added. +type StructType struct { + // Name is the name of the struct type. + Name string + + // Fields is the list of fields in the struct. + // It is a COMPATIBLE change to add new fields to an unsealed struct, + // but it is an INCOMPATIBLE change to add new fields to a sealed struct. + // + // A sealed struct cannot reference any unsealed structs directly or + // transitively because these types allow adding new fields. + Fields []Field + + // Sealed is true if it is an INCOMPATIBLE change to add new fields to the struct. + // It is a COMPATIBLE change to change an unsealed struct to sealed, but it is + // an INCOMPATIBLE change to change a sealed struct to unsealed. + Sealed bool +} diff --git a/schema/testing/appdatasim/app_data_test.go b/schema/testing/appdatasim/app_data_test.go index eba8a8984ffb..146f9a398e98 100644 --- a/schema/testing/appdatasim/app_data_test.go +++ b/schema/testing/appdatasim/app_data_test.go @@ -24,7 +24,7 @@ func TestAppSimulator_mirror(t *testing.T) { }) } -func testAppSimulatorMirror(t *testing.T, retainDeletes bool) { // nolint: thelper // this isn't a test helper function +func testAppSimulatorMirror(t *testing.T, retainDeletes bool) { //nolint: thelper // this isn't a test helper function stateSimOpts := statesim.Options{CanRetainDeletions: retainDeletes} mirror, err := NewSimulator(Options{ StateSimOptions: stateSimOpts, diff --git a/schema/type.go b/schema/type.go index f441829bb132..dfbc839ae0d4 100644 --- a/schema/type.go +++ b/schema/type.go @@ -18,7 +18,7 @@ type Type interface { type ReferenceType interface { Type - // IsReferenceType is implemented if this is a reference type. + // isReferenceType is implemented if this is a reference type. isReferenceType() } diff --git a/scripts/build/linting.mk b/scripts/build/linting.mk index 6e723c5f84f7..d174a06372f7 100644 --- a/scripts/build/linting.mk +++ b/scripts/build/linting.mk @@ -1,4 +1,4 @@ -golangci_version=v1.60.1 +golangci_version=v1.61.0 golangci_installed_version=$(shell golangci-lint version --format short 2>/dev/null) #? setup-pre-commit: Set pre-commit git hook diff --git a/scripts/build/simulations.mk b/scripts/build/simulations.mk index 4020d468a920..75182afc2cdd 100644 --- a/scripts/build/simulations.mk +++ b/scripts/build/simulations.mk @@ -2,7 +2,7 @@ #? test-sim-nondeterminism: Run non-determinism test for simapp test-sim-nondeterminism: @echo "Running non-determinism test..." - @cd ${CURRENT_DIR}/simapp && go test -mod=readonly -timeout=30m -tags='sims' -run TestAppStateDeterminism \ + @cd ${CURRENT_DIR}/simapp && go test -failfast -mod=readonly -timeout=30m -tags='sims' -run TestAppStateDeterminism \ -NumBlocks=100 -BlockSize=200 -Period=0 # Requires an exported plugin. See store/streaming/README.md for documentation. @@ -16,45 +16,46 @@ test-sim-nondeterminism: # make test-sim-nondeterminism-streaming test-sim-nondeterminism-streaming: @echo "Running non-determinism-streaming test..." - @cd ${CURRENT_DIR}/simapp && go test -mod=readonly -timeout=30m -tags='sims' -run TestAppStateDeterminism \ + @cd ${CURRENT_DIR}/simapp && go test -failfast -mod=readonly -timeout=30m -tags='sims' -run TestAppStateDeterminism \ -NumBlocks=100 -BlockSize=200 -Period=0 -EnableStreaming=true test-sim-custom-genesis-fast: @echo "Running custom genesis simulation..." @echo "By default, ${HOME}/.simapp/config/genesis.json will be used." - @cd ${CURRENT_DIR}/simapp && go test -mod=readonly -timeout=30m -tags='sims' -run TestFullAppSimulation -Genesis=${HOME}/.simapp/config/genesis.json \ + @cd ${CURRENT_DIR}/simapp && go test -failfast -mod=readonly -timeout=30m -tags='sims' -run TestFullAppSimulation -Genesis=${HOME}/.simapp/config/genesis.json \ -NumBlocks=100 -BlockSize=200 -Seed=99 -Period=5 -SigverifyTx=false test-sim-import-export: @echo "Running application import/export simulation. This may take several minutes..." - @cd ${CURRENT_DIR}/simapp && go test -mod=readonly -timeout 20m -tags='sims' -run TestAppImportExport \ + @cd ${CURRENT_DIR}/simapp && go test -failfast -mod=readonly -timeout 20m -tags='sims' -run TestAppImportExport \ -NumBlocks=50 -Period=5 test-sim-after-import: @echo "Running application simulation-after-import. This may take several minutes..." - @cd ${CURRENT_DIR}/simapp && go test -mod=readonly -timeout 30m -tags='sims' -run TestAppSimulationAfterImport \ + @cd ${CURRENT_DIR}/simapp && go test -failfast -mod=readonly -timeout 30m -tags='sims' -run TestAppSimulationAfterImport \ -NumBlocks=50 -Period=5 test-sim-custom-genesis-multi-seed: @echo "Running multi-seed custom genesis simulation..." @echo "By default, ${HOME}/.simapp/config/genesis.json will be used." - @cd ${CURRENT_DIR}/simapp && go test -mod=readonly -timeout 30m -tags='sims' -run TestFullAppSimulation -Genesis=${HOME}/.simapp/config/genesis.json \ + @cd ${CURRENT_DIR}/simapp && go test -failfast -mod=readonly -timeout 30m -tags='sims' -run TestFullAppSimulation -Genesis=${HOME}/.simapp/config/genesis.json \ -NumBlocks=400 -Period=5 test-sim-multi-seed-long: @echo "Running long multi-seed application simulation. This may take awhile!" - @cd ${CURRENT_DIR}/simapp && go test -mod=readonly -timeout=2h -tags='sims' -run TestFullAppSimulation \ + @cd ${CURRENT_DIR}/simapp && go test -failfast -mod=readonly -timeout=2h -tags='sims' -run TestFullAppSimulation \ -NumBlocks=150 -Period=50 test-sim-multi-seed-short: @echo "Running short multi-seed application simulation. This may take awhile!" - @cd ${CURRENT_DIR}/simapp && go test -mod=readonly -timeout 30m -tags='sims' -run TestFullAppSimulation \ - -NumBlocks=50 -Period=10 + @cd ${CURRENT_DIR}/simapp && go test -failfast -mod=readonly -timeout 30m -tags='sims' -run TestFullAppSimulation \ + -NumBlocks=50 -Period=10 -FauxMerkle=true + test-sim-benchmark-invariants: @echo "Running simulation invariant benchmarks..." - cd ${CURRENT_DIR}/simapp && go test -mod=readonly -benchmem -bench=BenchmarkInvariants -tags='sims' -run=^$ \ + cd ${CURRENT_DIR}/simapp && go test -failfast -mod=readonly -benchmem -bench=BenchmarkInvariants -tags='sims' -run=^$ \ -Enabled=true -NumBlocks=1000 -BlockSize=200 \ -Period=1 -Commit=true -Seed=57 -v -timeout 24h @@ -77,50 +78,23 @@ SIM_COMMIT ?= true test-sim-fuzz: @echo "Running application fuzz for numBlocks=2, blockSize=20. This may take awhile!" #ld flags are a quick fix to make it work on current osx - @cd ${CURRENT_DIR}/simapp && go test -mod=readonly -json -tags='sims' -ldflags="-extldflags=-Wl,-ld_classic" -timeout=60m -fuzztime=60m -run=^$$ -fuzz=FuzzFullAppSimulation -GenesisTime=1714720615 -NumBlocks=2 -BlockSize=20 + @cd ${CURRENT_DIR}/simapp && go test -failfast -mod=readonly -json -tags='sims' -ldflags="-extldflags=-Wl,-ld_classic" -timeout=60m -fuzztime=60m -run=^$$ -fuzz=FuzzFullAppSimulation -GenesisTime=1714720615 -NumBlocks=2 -BlockSize=20 #? test-sim-benchmark: Run benchmark test for simapp test-sim-benchmark: @echo "Running application benchmark for numBlocks=$(SIM_NUM_BLOCKS), blockSize=$(SIM_BLOCK_SIZE). This may take awhile!" - @cd ${CURRENT_DIR}/simapp && go test -mod=readonly -tags='sims' -run=^$$ $(.) -bench ^BenchmarkFullAppSimulation$$ \ + @cd ${CURRENT_DIR}/simapp && go test -failfast -mod=readonly -tags='sims' -run=^$$ $(.) -bench ^BenchmarkFullAppSimulation$$ \ -Enabled=true -NumBlocks=$(SIM_NUM_BLOCKS) -BlockSize=$(SIM_BLOCK_SIZE) -Commit=$(SIM_COMMIT) -timeout 24h -# Requires an exported plugin. See store/streaming/README.md for documentation. -# -# example: -# export COSMOS_SDK_ABCI_V1= -# make test-sim-benchmark-streaming -# -# Using the built-in examples: -# export COSMOS_SDK_ABCI_V1=/store/streaming/abci/examples/file/file -# make test-sim-benchmark-streaming -test-sim-benchmark-streaming: - @echo "Running application benchmark for numBlocks=$(SIM_NUM_BLOCKS), blockSize=$(SIM_BLOCK_SIZE). This may take awhile!" - @cd ${CURRENT_DIR}/simapp && go test -mod=readonly -tags='sims' -run=^$$ $(.) -bench ^BenchmarkFullAppSimulation$$ \ - -Enabled=true -NumBlocks=$(SIM_NUM_BLOCKS) -BlockSize=$(SIM_BLOCK_SIZE) -Commit=$(SIM_COMMIT) -timeout 24h -EnableStreaming=true test-sim-profile: @echo "Running application benchmark for numBlocks=$(SIM_NUM_BLOCKS), blockSize=$(SIM_BLOCK_SIZE). This may take awhile!" - @cd ${CURRENT_DIR}/simapp && go test -mod=readonly -tags='sims' -benchmem -run=^$$ $(.) -bench ^BenchmarkFullAppSimulation$$ \ + @cd ${CURRENT_DIR}/simapp && go test -failfast -mod=readonly -tags='sims' -benchmem -run=^$$ $(.) -bench ^BenchmarkFullAppSimulation$$ \ -Enabled=true -NumBlocks=$(SIM_NUM_BLOCKS) -BlockSize=$(SIM_BLOCK_SIZE) -Commit=$(SIM_COMMIT) -timeout 24h -cpuprofile cpu.out -memprofile mem.out -# Requires an exported plugin. See store/streaming/README.md for documentation. -# -# example: -# export COSMOS_SDK_ABCI_V1= -# make test-sim-profile-streaming -# -# Using the built-in examples: -# export COSMOS_SDK_ABCI_V1=/store/streaming/abci/examples/file/file -# make test-sim-profile-streaming -test-sim-profile-streaming: - @echo "Running application benchmark for numBlocks=$(SIM_NUM_BLOCKS), blockSize=$(SIM_BLOCK_SIZE). This may take awhile!" - @cd ${CURRENT_DIR}/simapp && go test -mod=readonly -tags='sims' -benchmem -run=^$$ $(.) -bench ^BenchmarkFullAppSimulation$$ \ - -Enabled=true -NumBlocks=$(SIM_NUM_BLOCKS) -BlockSize=$(SIM_BLOCK_SIZE) -Commit=$(SIM_COMMIT) -timeout 24h -cpuprofile cpu.out -memprofile mem.out -EnableStreaming=true - .PHONY: test-sim-profile test-sim-benchmark test-sim-fuzz #? benchmark: Run benchmark tests benchmark: - @go test -mod=readonly -bench=. $(PACKAGES_NOSIMULATION) + @go test -failfast -mod=readonly -bench=. $(PACKAGES_NOSIMULATION) .PHONY: benchmark diff --git a/scripts/local-testnet.sh b/scripts/local-testnet.sh deleted file mode 100644 index c73710dbab1e..000000000000 --- a/scripts/local-testnet.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/usr/bin/env bash - -set -o errexit -set -o nounset -set -x - -ROOT=$PWD - -SIMD="$ROOT/build/simdv2" - -COSMOS_BUILD_OPTIONS=v2 make build - -$SIMD testnet init-files --chain-id=testing --output-dir="$HOME/.testnet" --validator-count=3 --keyring-backend=test --minimum-gas-prices=0.000001stake --commit-timeout=900ms --single-host - -$SIMD start --log_level=info --home "$HOME/.testnet/node0/simdv2" & -$SIMD start --log_level=info --home "$HOME/.testnet/node1/simdv2" & -$SIMD start --log_level=info --home "$HOME/.testnet/node2/simdv2" \ No newline at end of file diff --git a/scripts/mockgen.sh b/scripts/mockgen.sh index 57ef89cef1c5..1018534c81bc 100755 --- a/scripts/mockgen.sh +++ b/scripts/mockgen.sh @@ -13,7 +13,7 @@ $mockgen_cmd -source=x/nft/expected_keepers.go -package testutil -destination x/ $mockgen_cmd -source=x/feegrant/expected_keepers.go -package testutil -destination x/feegrant/testutil/expected_keepers_mocks.go $mockgen_cmd -source=x/mint/types/expected_keepers.go -package testutil -destination x/mint/testutil/expected_keepers_mocks.go $mockgen_cmd -source=x/auth/tx/config/expected_keepers.go -package testutil -destination x/auth/tx/testutil/expected_keepers_mocks.go -# $mockgen_cmd -source=x/auth/types/expected_keepers.go -package testutil -destination x/auth/testutil/expected_keepers_mocks.go +$mockgen_cmd -source=x/auth/types/expected_keepers.go -package testutil -destination x/auth/testutil/expected_keepers_mocks.go $mockgen_cmd -source=x/auth/ante/expected_keepers.go -package testutil -destination x/auth/ante/testutil/expected_keepers_mocks.go $mockgen_cmd -source=x/authz/expected_keepers.go -package testutil -destination x/authz/testutil/expected_keepers_mocks.go $mockgen_cmd -source=x/bank/types/expected_keepers.go -package testutil -destination x/bank/testutil/expected_keepers_mocks.go @@ -24,7 +24,7 @@ $mockgen_cmd -source=x/slashing/types/expected_keepers.go -package testutil -des $mockgen_cmd -source=x/genutil/types/expected_keepers.go -package testutil -destination x/genutil/testutil/expected_keepers_mocks.go $mockgen_cmd -source=x/gov/testutil/expected_keepers.go -package testutil -destination x/gov/testutil/expected_keepers_mocks.go $mockgen_cmd -source=x/staking/types/expected_keepers.go -package testutil -destination x/staking/testutil/expected_keepers_mocks.go -# $mockgen_cmd -source=x/auth/vesting/types/expected_keepers.go -package testutil -destination x/auth/vesting/testutil/expected_keepers_mocks.go +$mockgen_cmd -source=x/auth/vesting/types/expected_keepers.go -package testutil -destination x/auth/vesting/testutil/expected_keepers_mocks.go $mockgen_cmd -source=x/protocolpool/types/expected_keepers.go -package testutil -destination x/protocolpool/testutil/expected_keepers_mocks.go $mockgen_cmd -source=x/upgrade/types/expected_keepers.go -package testutil -destination x/upgrade/testutil/expected_keepers_mocks.go $mockgen_cmd -source=core/gas/service.go -package gas -destination core/testing/gas/service_mocks.go diff --git a/server/cmt_cmds.go b/server/cmt_cmds.go index e4c84364dd5a..d511cc105696 100644 --- a/server/cmt_cmds.go +++ b/server/cmt_cmds.go @@ -368,7 +368,7 @@ func BootstrapStateCmd[T types.Application](appCreator types.AppCreator[T]) *cob Use: "bootstrap-state", Short: "Bootstrap CometBFT state at an arbitrary block height using a light client", Args: cobra.NoArgs, - Example: fmt.Sprintf("%s bootstrap-state --height 1000000", version.AppName), + Example: "bootstrap-state --height 1000000", RunE: func(cmd *cobra.Command, args []string) error { serverCtx := GetServerContextFromCmd(cmd) logger := log.NewLogger(cmd.OutOrStdout()) diff --git a/server/grpc/gogoreflection/fix_registration.go b/server/grpc/gogoreflection/fix_registration.go index ab1a18f592e9..5704f054ff61 100644 --- a/server/grpc/gogoreflection/fix_registration.go +++ b/server/grpc/gogoreflection/fix_registration.go @@ -3,10 +3,9 @@ package gogoreflection import ( "reflect" + _ "github.com/cosmos/cosmos-proto" // look above _ "github.com/cosmos/gogoproto/gogoproto" // required so it does register the gogoproto file descriptor gogoproto "github.com/cosmos/gogoproto/proto" - - _ "github.com/cosmos/cosmos-proto" // look above "github.com/golang/protobuf/proto" //nolint:staticcheck // migrate in a future pr ) @@ -42,12 +41,12 @@ func getExtension(extID int32, m proto.Message) *gogoproto.ExtensionDesc { for id, desc := range proto.RegisteredExtensions(m) { //nolint:staticcheck // keep for backward compatibility if id == extID { return &gogoproto.ExtensionDesc{ - ExtendedType: desc.ExtendedType, //nolint:staticcheck // keep for backward compatibility - ExtensionType: desc.ExtensionType, //nolint:staticcheck // keep for backward compatibility - Field: desc.Field, //nolint:staticcheck // keep for backward compatibility - Name: desc.Name, //nolint:staticcheck // keep for backward compatibility - Tag: desc.Tag, //nolint:staticcheck // keep for backward compatibility - Filename: desc.Filename, //nolint:staticcheck // keep for backward compatibility + ExtendedType: desc.ExtendedType, + ExtensionType: desc.ExtensionType, + Field: desc.Field, + Name: desc.Name, + Tag: desc.Tag, + Filename: desc.Filename, } } } diff --git a/server/grpc/gogoreflection/serverreflection.go b/server/grpc/gogoreflection/serverreflection.go index 559548cb31b3..11213a19d82f 100644 --- a/server/grpc/gogoreflection/serverreflection.go +++ b/server/grpc/gogoreflection/serverreflection.go @@ -184,7 +184,7 @@ func fqn(prefix, name string) string { // fileDescForType gets the file descriptor for the given type. // The given type should be a proto message. func (s *serverReflectionServer) fileDescForType(st reflect.Type) (*dpb.FileDescriptorProto, error) { - m, ok := reflect.Zero(reflect.PtrTo(st)).Interface().(protoMessage) + m, ok := reflect.Zero(reflect.PointerTo(st)).Interface().(protoMessage) if !ok { return nil, fmt.Errorf("failed to create message from type: %v", st) } @@ -232,7 +232,7 @@ func typeForName(name string) (reflect.Type, error) { } func fileDescContainingExtension(st reflect.Type, ext int32) (*dpb.FileDescriptorProto, error) { - m, ok := reflect.Zero(reflect.PtrTo(st)).Interface().(proto.Message) + m, ok := reflect.Zero(reflect.PointerTo(st)).Interface().(proto.Message) if !ok { return nil, fmt.Errorf("failed to create message from type: %v", st) } @@ -247,7 +247,7 @@ func fileDescContainingExtension(st reflect.Type, ext int32) (*dpb.FileDescripto } func (s *serverReflectionServer) allExtensionNumbersForType(st reflect.Type) ([]int32, error) { - m, ok := reflect.Zero(reflect.PtrTo(st)).Interface().(proto.Message) + m, ok := reflect.Zero(reflect.PointerTo(st)).Interface().(proto.Message) if !ok { return nil, fmt.Errorf("failed to create message from type: %v", st) } diff --git a/server/pruning_test.go b/server/pruning_test.go index 0c162fad61fe..08e1a6d0773c 100644 --- a/server/pruning_test.go +++ b/server/pruning_test.go @@ -49,8 +49,6 @@ func TestGetPruningOptionsFromFlags(t *testing.T) { } for _, tt := range tests { - tt := tt - t.Run(tt.name, func(j *testing.T) { viper.Reset() viper.SetDefault(FlagPruning, pruningtypes.PruningOptionDefault) diff --git a/server/start.go b/server/start.go index dce5ae198e6a..f9ae56676305 100644 --- a/server/start.go +++ b/server/start.go @@ -9,6 +9,7 @@ import ( "io" "net" "os" + "path/filepath" "runtime/pprof" "strings" "time" @@ -374,9 +375,7 @@ func startCmtNode( return nil, cleanupFn, err } - pv, err := pvm.LoadOrGenFilePV(cfg.PrivValidatorKeyFile(), cfg.PrivValidatorStateFile(), func() (cmtcrypto.PrivKey, error) { - return cmted25519.GenPrivKey(), nil - }) // TODO: make this modular + pv, err := pvm.LoadOrGenFilePV(cfg.PrivValidatorKeyFile(), cfg.PrivValidatorStateFile(), app.ValidatorKeyProvider()) if err != nil { return nil, cleanupFn, err } @@ -782,6 +781,17 @@ func testnetify[T types.Application](ctx *Context, testnetAppCreator types.AppCr return nil, err } + // Regenerate addrbook.json to prevent peers on old network from causing error logs. + addrBookPath := filepath.Join(config.RootDir, "config", "addrbook.json") + if err := os.Remove(addrBookPath); err != nil && !os.IsNotExist(err) { + return nil, fmt.Errorf("failed to remove existing addrbook.json: %w", err) + } + + emptyAddrBook := []byte("{}") + if err := os.WriteFile(addrBookPath, emptyAddrBook, 0o600); err != nil { + return nil, fmt.Errorf("failed to create empty addrbook.json: %w", err) + } + // Load the comet genesis doc provider. genDocProvider := node.DefaultGenesisDocProviderFunc(config) @@ -832,7 +842,7 @@ func testnetify[T types.Application](ctx *Context, testnetAppCreator types.AppCr _, context := getCtx(ctx, true) clientCreator := proxy.NewLocalClientCreator(cmtApp) metrics := node.DefaultMetricsProvider(cmtcfg.DefaultConfig().Instrumentation) - _, _, _, _, _, proxyMetrics, _, _ := metrics(genDoc.ChainID) // nolint: dogsled // function from comet + _, _, _, _, _, proxyMetrics, _, _ := metrics(genDoc.ChainID) //nolint: dogsled // function from comet proxyApp := proxy.NewAppConns(clientCreator, proxyMetrics) if err := proxyApp.Start(); err != nil { return nil, fmt.Errorf("error starting proxy app connections: %w", err) diff --git a/server/types/app.go b/server/types/app.go index d08cfff0ea9b..ca0a55ca1a0f 100644 --- a/server/types/app.go +++ b/server/types/app.go @@ -5,6 +5,7 @@ import ( "io" cmtproto "github.com/cometbft/cometbft/api/cometbft/types/v1" + cmtcrypto "github.com/cometbft/cometbft/crypto" cmttypes "github.com/cometbft/cometbft/types" "github.com/cosmos/gogoproto/grpc" @@ -57,6 +58,9 @@ type ( // SnapshotManager return the snapshot manager SnapshotManager() *snapshots.Manager + // ValidatorKeyProvider returns a function that generates a validator key + ValidatorKeyProvider() func() (cmtcrypto.PrivKey, error) + // Close is called in start cmd to gracefully cleanup resources. // Must be safe to be called multiple times. Close() error diff --git a/server/util_test.go b/server/util_test.go index ea9489a03685..d03f1ad10fe6 100644 --- a/server/util_test.go +++ b/server/util_test.go @@ -11,7 +11,7 @@ import ( "testing" cmtcfg "github.com/cometbft/cometbft/config" - db "github.com/cosmos/cosmos-db" + dbm "github.com/cosmos/cosmos-db" "github.com/spf13/cobra" "github.com/spf13/viper" "github.com/stretchr/testify/require" @@ -42,11 +42,11 @@ func preRunETestImpl(cmd *cobra.Command, args []string) error { func TestGetAppDBBackend(t *testing.T) { v := viper.New() - require.Equal(t, server.GetAppDBBackend(v), db.GoLevelDBBackend) + require.Equal(t, server.GetAppDBBackend(v), dbm.GoLevelDBBackend) v.Set("db_backend", "dbtype1") // value from CometBFT config - require.Equal(t, server.GetAppDBBackend(v), db.BackendType("dbtype1")) + require.Equal(t, server.GetAppDBBackend(v), dbm.BackendType("dbtype1")) v.Set("app-db-backend", "dbtype2") // value from app.toml - require.Equal(t, server.GetAppDBBackend(v), db.BackendType("dbtype2")) + require.Equal(t, server.GetAppDBBackend(v), dbm.BackendType("dbtype2")) } func TestInterceptConfigsPreRunHandlerCreatesConfigFilesWhenMissing(t *testing.T) { diff --git a/server/v2/api/grpc/config.go b/server/v2/api/grpc/config.go index 86fb514e70d8..4e9cabc7a418 100644 --- a/server/v2/api/grpc/config.go +++ b/server/v2/api/grpc/config.go @@ -4,14 +4,9 @@ import "math" func DefaultConfig() *Config { return &Config{ - Enable: true, - // DefaultGRPCAddress defines the default address to bind the gRPC server to. - Address: "localhost:9090", - // DefaultGRPCMaxRecvMsgSize defines the default gRPC max message size in - // bytes the server can receive. + Enable: true, + Address: "localhost:9090", MaxRecvMsgSize: 1024 * 1024 * 10, - // DefaultGRPCMaxSendMsgSize defines the default gRPC max message size in - // bytes the server can send. MaxSendMsgSize: math.MaxInt32, } } diff --git a/server/v2/api/grpc/gogoreflection/fix_registration.go b/server/v2/api/grpc/gogoreflection/fix_registration.go index ab1a18f592e9..5704f054ff61 100644 --- a/server/v2/api/grpc/gogoreflection/fix_registration.go +++ b/server/v2/api/grpc/gogoreflection/fix_registration.go @@ -3,10 +3,9 @@ package gogoreflection import ( "reflect" + _ "github.com/cosmos/cosmos-proto" // look above _ "github.com/cosmos/gogoproto/gogoproto" // required so it does register the gogoproto file descriptor gogoproto "github.com/cosmos/gogoproto/proto" - - _ "github.com/cosmos/cosmos-proto" // look above "github.com/golang/protobuf/proto" //nolint:staticcheck // migrate in a future pr ) @@ -42,12 +41,12 @@ func getExtension(extID int32, m proto.Message) *gogoproto.ExtensionDesc { for id, desc := range proto.RegisteredExtensions(m) { //nolint:staticcheck // keep for backward compatibility if id == extID { return &gogoproto.ExtensionDesc{ - ExtendedType: desc.ExtendedType, //nolint:staticcheck // keep for backward compatibility - ExtensionType: desc.ExtensionType, //nolint:staticcheck // keep for backward compatibility - Field: desc.Field, //nolint:staticcheck // keep for backward compatibility - Name: desc.Name, //nolint:staticcheck // keep for backward compatibility - Tag: desc.Tag, //nolint:staticcheck // keep for backward compatibility - Filename: desc.Filename, //nolint:staticcheck // keep for backward compatibility + ExtendedType: desc.ExtendedType, + ExtensionType: desc.ExtensionType, + Field: desc.Field, + Name: desc.Name, + Tag: desc.Tag, + Filename: desc.Filename, } } } diff --git a/server/v2/api/grpc/gogoreflection/serverreflection.go b/server/v2/api/grpc/gogoreflection/serverreflection.go index 79f520545a87..5bd26b467e00 100644 --- a/server/v2/api/grpc/gogoreflection/serverreflection.go +++ b/server/v2/api/grpc/gogoreflection/serverreflection.go @@ -188,7 +188,7 @@ func fqn(prefix, name string) string { // fileDescForType gets the file descriptor for the given type. // The given type should be a proto message. func (s *serverReflectionServer) fileDescForType(st reflect.Type) (*dpb.FileDescriptorProto, error) { - m, ok := reflect.Zero(reflect.PtrTo(st)).Interface().(protoMessage) + m, ok := reflect.Zero(reflect.PointerTo(st)).Interface().(protoMessage) if !ok { return nil, fmt.Errorf("failed to create message from type: %v", st) } @@ -236,7 +236,7 @@ func typeForName(name string) (reflect.Type, error) { } func fileDescContainingExtension(st reflect.Type, ext int32) (*dpb.FileDescriptorProto, error) { - m, ok := reflect.Zero(reflect.PtrTo(st)).Interface().(gogoproto.Message) + m, ok := reflect.Zero(reflect.PointerTo(st)).Interface().(gogoproto.Message) if !ok { return nil, fmt.Errorf("failed to create message from type: %v", st) } @@ -251,7 +251,7 @@ func fileDescContainingExtension(st reflect.Type, ext int32) (*dpb.FileDescripto } func (s *serverReflectionServer) allExtensionNumbersForType(st reflect.Type) ([]int32, error) { - m, ok := reflect.Zero(reflect.PtrTo(st)).Interface().(gogoproto.Message) + m, ok := reflect.Zero(reflect.PointerTo(st)).Interface().(gogoproto.Message) if !ok { return nil, fmt.Errorf("failed to create message from type: %v", st) } diff --git a/server/v2/api/grpc/server.go b/server/v2/api/grpc/server.go index 0003f2343222..7b70363f6f16 100644 --- a/server/v2/api/grpc/server.go +++ b/server/v2/api/grpc/server.go @@ -9,14 +9,18 @@ import ( "net" "slices" "strconv" + "strings" + "sync" - "github.com/cosmos/gogoproto/proto" + gogoproto "github.com/cosmos/gogoproto/proto" "github.com/spf13/pflag" "google.golang.org/grpc" "google.golang.org/grpc/codes" "google.golang.org/grpc/metadata" "google.golang.org/grpc/status" + "google.golang.org/protobuf/reflect/protoreflect" + appmodulev2 "cosmossdk.io/core/appmodule/v2" "cosmossdk.io/core/transaction" "cosmossdk.io/log" serverv2 "cosmossdk.io/server/v2" @@ -53,7 +57,7 @@ func (s *Server[T]) Init(appI serverv2.AppI[T], cfg map[string]any, logger log.L return fmt.Errorf("failed to unmarshal config: %w", err) } } - methodsMap := appI.GetGPRCMethodsToMessageMap() + methodsMap := appI.GetQueryHandlers() grpcSrv := grpc.NewServer( grpc.ForceServerCodec(newProtoCodec(appI.InterfaceRegistry()).GRPCCodec()), @@ -80,21 +84,42 @@ func (s *Server[T]) StartCmdFlags() *pflag.FlagSet { return flags } -func makeUnknownServiceHandler(messageMap map[string]func() proto.Message, querier interface { - Query(ctx context.Context, version uint64, msg proto.Message) (proto.Message, error) +func makeUnknownServiceHandler(handlers map[string]appmodulev2.Handler, querier interface { + Query(ctx context.Context, version uint64, msg gogoproto.Message) (gogoproto.Message, error) }, ) grpc.StreamHandler { + getRegistry := sync.OnceValues(gogoproto.MergedRegistry) + return func(srv any, stream grpc.ServerStream) error { method, ok := grpc.MethodFromServerStream(stream) if !ok { return status.Error(codes.InvalidArgument, "unable to get method") } - makeMsg, exists := messageMap[method] + // if this fails we cannot serve queries anymore... + registry, err := getRegistry() + if err != nil { + return fmt.Errorf("failed to get registry: %w", err) + } + + method = strings.TrimPrefix(method, "/") + fullName := protoreflect.FullName(strings.ReplaceAll(method, "/", ".")) + // get descriptor from the invoke method + desc, err := registry.FindDescriptorByName(fullName) + if err != nil { + return fmt.Errorf("failed to find descriptor %s: %w", method, err) + } + md, ok := desc.(protoreflect.MethodDescriptor) + if !ok { + return fmt.Errorf("%s is not a method", method) + } + // find handler + handler, exists := handlers[string(md.Input().FullName())] if !exists { return status.Errorf(codes.Unimplemented, "gRPC method %s is not handled", method) } + for { - req := makeMsg() + req := handler.MakeMsg() err := stream.RecvMsg(req) if err != nil { if errors.Is(err, io.EOF) { @@ -148,7 +173,7 @@ func (s *Server[T]) Name() string { } func (s *Server[T]) Config() any { - if s.config == nil || s.config == (&Config{}) { + if s.config == nil || s.config.Address == "" { cfg := DefaultConfig() // overwrite the default config with the provided options for _, opt := range s.cfgOptions { @@ -163,6 +188,7 @@ func (s *Server[T]) Config() any { func (s *Server[T]) Start(ctx context.Context) error { if !s.config.Enable { + s.logger.Info(fmt.Sprintf("%s server is disabled via config", s.Name())) return nil } @@ -171,24 +197,12 @@ func (s *Server[T]) Start(ctx context.Context) error { return fmt.Errorf("failed to listen on address %s: %w", s.config.Address, err) } - errCh := make(chan error) - - // Start the gRPC in an external goroutine as Serve is blocking and will return - // an error upon failure, which we'll send on the error channel that will be - // consumed by the for block below. - go func() { - s.logger.Info("starting gRPC server...", "address", s.config.Address) - errCh <- s.grpcSrv.Serve(listener) - }() - - // Start a blocking select to wait for an indication to stop the server or that - // the server failed to start properly. - err = <-errCh - if err != nil { - s.logger.Error("failed to start gRPC server", "err", err) + s.logger.Info("starting gRPC server...", "address", s.config.Address) + if err := s.grpcSrv.Serve(listener); err != nil { + return fmt.Errorf("failed to start gRPC server: %w", err) } - return err + return nil } func (s *Server[T]) Stop(ctx context.Context) error { @@ -198,6 +212,10 @@ func (s *Server[T]) Stop(ctx context.Context) error { s.logger.Info("stopping gRPC server...", "address", s.config.Address) s.grpcSrv.GracefulStop() - return nil } + +// GetGRPCServer returns the underlying gRPC server. +func (s *Server[T]) GetGRPCServer() *grpc.Server { + return s.grpcSrv +} diff --git a/server/v2/api/grpcgateway/config.go b/server/v2/api/grpcgateway/config.go index c5ccb3bfe2d1..773eeb4d58ad 100644 --- a/server/v2/api/grpcgateway/config.go +++ b/server/v2/api/grpcgateway/config.go @@ -2,13 +2,17 @@ package grpcgateway func DefaultConfig() *Config { return &Config{ - Enable: true, + Enable: true, + Address: "localhost:1317", } } type Config struct { // Enable defines if the gRPC-gateway should be enabled. Enable bool `mapstructure:"enable" toml:"enable" comment:"Enable defines if the gRPC-gateway should be enabled."` + + // Address defines the address the gRPC-gateway server binds to. + Address string `mapstructure:"address" toml:"address" comment:"Address defines the address the gRPC-gateway server binds to."` } type CfgOption func(*Config) diff --git a/server/v2/api/grpcgateway/server.go b/server/v2/api/grpcgateway/server.go index 05a6bf1aa829..412c4e4ad81d 100644 --- a/server/v2/api/grpcgateway/server.go +++ b/server/v2/api/grpcgateway/server.go @@ -8,7 +8,6 @@ import ( gateway "github.com/cosmos/gogogateway" "github.com/cosmos/gogoproto/jsonpb" - "github.com/gorilla/mux" "github.com/grpc-ecosystem/grpc-gateway/runtime" "google.golang.org/grpc" @@ -17,26 +16,25 @@ import ( serverv2 "cosmossdk.io/server/v2" ) -var _ serverv2.ServerComponent[transaction.Tx] = (*GRPCGatewayServer[transaction.Tx])(nil) - -const ( - ServerName = "grpc-gateway" - - // GRPCBlockHeightHeader is the gRPC header for block height. - GRPCBlockHeightHeader = "x-cosmos-block-height" +var ( + _ serverv2.ServerComponent[transaction.Tx] = (*Server[transaction.Tx])(nil) + _ serverv2.HasConfig = (*Server[transaction.Tx])(nil) ) -type GRPCGatewayServer[T transaction.Tx] struct { +const ServerName = "grpc-gateway" + +type Server[T transaction.Tx] struct { logger log.Logger config *Config cfgOptions []CfgOption - GRPCSrv *grpc.Server - GRPCGatewayRouter *runtime.ServeMux + server *http.Server + gRPCSrv *grpc.Server + gRPCGatewayRouter *runtime.ServeMux } // New creates a new gRPC-gateway server. -func New[T transaction.Tx](grpcSrv *grpc.Server, ir jsonpb.AnyResolver, cfgOptions ...CfgOption) *GRPCGatewayServer[T] { +func New[T transaction.Tx](grpcSrv *grpc.Server, ir jsonpb.AnyResolver, cfgOptions ...CfgOption) *Server[T] { // The default JSON marshaller used by the gRPC-Gateway is unable to marshal non-nullable non-scalar fields. // Using the gogo/gateway package with the gRPC-Gateway WithMarshaler option fixes the scalar field marshaling issue. marshalerOption := &gateway.JSONPb{ @@ -46,9 +44,9 @@ func New[T transaction.Tx](grpcSrv *grpc.Server, ir jsonpb.AnyResolver, cfgOptio AnyResolver: ir, } - return &GRPCGatewayServer[T]{ - GRPCSrv: grpcSrv, - GRPCGatewayRouter: runtime.NewServeMux( + return &Server[T]{ + gRPCSrv: grpcSrv, + gRPCGatewayRouter: runtime.NewServeMux( // Custom marshaler option is required for gogo proto runtime.WithMarshalerOption(runtime.MIMEWildcard, marshalerOption), @@ -64,12 +62,12 @@ func New[T transaction.Tx](grpcSrv *grpc.Server, ir jsonpb.AnyResolver, cfgOptio } } -func (g *GRPCGatewayServer[T]) Name() string { +func (s *Server[T]) Name() string { return ServerName } -func (s *GRPCGatewayServer[T]) Config() any { - if s.config == nil || s.config == (&Config{}) { +func (s *Server[T]) Config() any { + if s.config == nil || s.config.Address == "" { cfg := DefaultConfig() // overwrite the default config with the provided options for _, opt := range s.cfgOptions { @@ -82,7 +80,7 @@ func (s *GRPCGatewayServer[T]) Config() any { return s.config } -func (s *GRPCGatewayServer[T]) Init(appI serverv2.AppI[transaction.Tx], cfg map[string]any, logger log.Logger) error { +func (s *Server[T]) Init(appI serverv2.AppI[transaction.Tx], cfg map[string]any, logger log.Logger) error { serverCfg := s.Config().(*Config) if len(cfg) > 0 { if err := serverv2.UnmarshalSubConfig(cfg, s.Name(), &serverCfg); err != nil { @@ -90,42 +88,43 @@ func (s *GRPCGatewayServer[T]) Init(appI serverv2.AppI[transaction.Tx], cfg map[ } } - // Register the gRPC-Gateway server. - // appI.RegisterGRPCGatewayRoutes(s.GRPCGatewayRouter, s.GRPCSrv) + // TODO: register the gRPC-Gateway routes - s.logger = logger + s.logger = logger.With(log.ModuleKey, s.Name()) s.config = serverCfg return nil } -func (s *GRPCGatewayServer[T]) Start(ctx context.Context) error { +func (s *Server[T]) Start(ctx context.Context) error { if !s.config.Enable { + s.logger.Info(fmt.Sprintf("%s server is disabled via config", s.Name())) return nil } - // TODO start a normal Go http server (and do not leverage comet's like https://github.com/cosmos/cosmos-sdk/blob/9df6019de6ee7999fe9864bac836deb2f36dd44a/server/api/server.go#L98) + mux := http.NewServeMux() + mux.Handle("/", s.gRPCGatewayRouter) - return nil -} + s.server = &http.Server{ + Addr: s.config.Address, + Handler: mux, + } -func (s *GRPCGatewayServer[T]) Stop(ctx context.Context) error { - if !s.config.Enable { - return nil + s.logger.Info("starting gRPC-Gateway server...", "address", s.config.Address) + if err := s.server.ListenAndServe(); err != nil && err != http.ErrServerClosed { + return fmt.Errorf("failed to start gRPC-Gateway server: %w", err) } return nil } -// Register implements registers a grpc-gateway server -func (s *GRPCGatewayServer[T]) Register(r mux.Router) error { - // configure grpc-gatway server - r.PathPrefix("/").Handler(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { - // Fall back to grpc gateway server. - s.GRPCGatewayRouter.ServeHTTP(w, req) - })) +func (s *Server[T]) Stop(ctx context.Context) error { + if !s.config.Enable { + return nil + } - return nil + s.logger.Info("stopping gRPC-Gateway server...", "address", s.config.Address) + return s.server.Shutdown(ctx) } // CustomGRPCHeaderMatcher for mapping request headers to @@ -134,6 +133,9 @@ func (s *GRPCGatewayServer[T]) Register(r mux.Router) error { // gRPC metadata after removing prefix 'Grpc-Metadata-'. We can use this // CustomGRPCHeaderMatcher if headers don't start with `Grpc-Metadata-` func CustomGRPCHeaderMatcher(key string) (string, bool) { + // GRPCBlockHeightHeader is the gRPC header for block height. + const GRPCBlockHeightHeader = "x-cosmos-block-height" + switch strings.ToLower(key) { case GRPCBlockHeightHeader: return GRPCBlockHeightHeader, true diff --git a/server/v2/api/telemetry/config.go b/server/v2/api/telemetry/config.go index 63a37ed1f39d..2619665d1844 100644 --- a/server/v2/api/telemetry/config.go +++ b/server/v2/api/telemetry/config.go @@ -1,13 +1,32 @@ package telemetry -type Config struct { - // Prefixed with keys to separate services - ServiceName string `mapstructure:"service-name" toml:"service-name" comment:"Prefixed with keys to separate services."` +func DefaultConfig() *Config { + return &Config{ + Enable: true, + Address: "localhost:1318", + ServiceName: "", + EnableHostname: false, + EnableHostnameLabel: false, + EnableServiceLabel: false, + PrometheusRetentionTime: 0, + GlobalLabels: nil, + MetricsSink: "", + StatsdAddr: "", + DatadogHostname: "", + } +} - // Enabled enables the application telemetry functionality. When enabled, +type Config struct { + // Enable enables the application telemetry functionality. When enabled, // an in-memory sink is also enabled by default. Operators may also enabled // other sinks such as Prometheus. - Enabled bool `mapstructure:"enabled" toml:"enabled" comment:"Enabled enables the application telemetry functionality. When enabled, an in-memory sink is also enabled by default. Operators may also enabled other sinks such as Prometheus."` + Enable bool `mapstructure:"enable" toml:"enable" comment:"Enable enables the application telemetry functionality. When enabled, an in-memory sink is also enabled by default. Operators may also enabled other sinks such as Prometheus."` + + // Address defines the API server to listen on + Address string `mapstructure:"address" toml:"address" comment:"Address defines the metrics server address to bind to."` + + // Prefixed with keys to separate services + ServiceName string `mapstructure:"service-name" toml:"service-name" comment:"Prefixed with keys to separate services."` // Enable prefixing gauge values with hostname EnableHostname bool `mapstructure:"enable-hostname" toml:"enable-hostname" comment:"Enable prefixing gauge values with hostname."` diff --git a/server/v2/api/telemetry/metrics.go b/server/v2/api/telemetry/metrics.go index 39055af6739b..3dd9e3d55b94 100644 --- a/server/v2/api/telemetry/metrics.go +++ b/server/v2/api/telemetry/metrics.go @@ -17,7 +17,7 @@ import ( // GlobalLabels defines the set of global labels that will be applied to all // metrics emitted using the telemetry package function wrappers. -var GlobalLabels = []metrics.Label{} // nolint: ignore // false positive +var GlobalLabels = []metrics.Label{} //nolint: ignore // false positive // NewLabel creates a new instance of Label with name and value func NewLabel(name, value string) metrics.Label { @@ -57,12 +57,8 @@ type GatherResponse struct { ContentType string } -// New creates a new instance of Metrics -func New(cfg Config) (_ *Metrics, rerr error) { - if !cfg.Enabled { - return nil, nil - } - +// NewMetrics creates a new instance of Metrics +func NewMetrics(cfg *Config) (*Metrics, error) { if numGlobalLabels := len(cfg.GlobalLabels); numGlobalLabels > 0 { parsedGlobalLabels := make([]metrics.Label, numGlobalLabels) for i, gl := range cfg.GlobalLabels { @@ -89,12 +85,11 @@ func New(cfg Config) (_ *Metrics, rerr error) { sink = memSink inMemSig := metrics.DefaultInmemSignal(memSink) defer func() { - if rerr != nil { + if err != nil { inMemSig.Stop() } }() } - if err != nil { return nil, err } diff --git a/server/v2/api/telemetry/server.go b/server/v2/api/telemetry/server.go index a944fc7f4f03..411b1bda797d 100644 --- a/server/v2/api/telemetry/server.go +++ b/server/v2/api/telemetry/server.go @@ -1,47 +1,126 @@ package telemetry import ( + "context" "encoding/json" "fmt" "net/http" "strings" - "github.com/gorilla/mux" + "cosmossdk.io/core/transaction" + "cosmossdk.io/log" + serverv2 "cosmossdk.io/server/v2" ) -func RegisterMetrics(r mux.Router, cfg Config) (*Metrics, error) { - m, err := New(cfg) +var ( + _ serverv2.ServerComponent[transaction.Tx] = (*Server[transaction.Tx])(nil) + _ serverv2.HasConfig = (*Server[transaction.Tx])(nil) +) + +const ServerName = "telemetry" + +type Server[T transaction.Tx] struct { + config *Config + logger log.Logger + server *http.Server + metrics *Metrics +} + +// New creates a new telemetry server. +func New[T transaction.Tx]() *Server[T] { + return &Server[T]{} +} + +// Name returns the server name. +func (s *Server[T]) Name() string { + return ServerName +} + +func (s *Server[T]) Config() any { + if s.config == nil || s.config.Address == "" { + return DefaultConfig() + } + + return s.config +} + +// Init implements serverv2.ServerComponent. +func (s *Server[T]) Init(appI serverv2.AppI[T], cfg map[string]any, logger log.Logger) error { + serverCfg := s.Config().(*Config) + if len(cfg) > 0 { + if err := serverv2.UnmarshalSubConfig(cfg, s.Name(), &serverCfg); err != nil { + return fmt.Errorf("failed to unmarshal config: %w", err) + } + } + s.config = serverCfg + s.logger = logger.With(log.ModuleKey, s.Name()) + + metrics, err := NewMetrics(s.config) if err != nil { - return nil, err + return fmt.Errorf("failed to initialize metrics: %w", err) } + s.metrics = metrics - metricsHandler := func(w http.ResponseWriter, r *http.Request) { - format := strings.TrimSpace(r.FormValue("format")) + return nil +} - gr, err := m.Gather(format) - if err != nil { - w.Header().Set("Content-Type", "application/json") - w.WriteHeader(http.StatusBadRequest) - bz, err := json.Marshal(errorResponse{Code: 400, Error: fmt.Sprintf("failed to gather metrics: %s", err)}) - if err != nil { - return - } - _, _ = w.Write(bz) +func (s *Server[T]) Start(ctx context.Context) error { + if !s.config.Enable { + s.logger.Info(fmt.Sprintf("%s server is disabled via config", s.Name())) + return nil + } - return - } + mux := http.NewServeMux() + mux.HandleFunc("/", s.metricsHandler) + // keeping /metrics for backwards compatibility + mux.HandleFunc("/metrics", func(w http.ResponseWriter, r *http.Request) { + http.Redirect(w, r, "/", http.StatusMovedPermanently) + }) - w.Header().Set("Content-Type", gr.ContentType) - _, _ = w.Write(gr.Metrics) + s.server = &http.Server{ + Addr: s.config.Address, + Handler: mux, } - r.HandleFunc("/metrics", metricsHandler).Methods("GET") + s.logger.Info("starting telemetry server...", "address", s.config.Address) + if err := s.server.ListenAndServe(); err != nil && err != http.ErrServerClosed { + return fmt.Errorf("failed to start telemetry server: %w", err) + } - return m, nil + return nil } -// errorResponse defines the attributes of a JSON error response. -type errorResponse struct { - Code int `json:"code,omitempty"` - Error string `json:"error"` +func (s *Server[T]) Stop(ctx context.Context) error { + if !s.config.Enable || s.server == nil { + return nil + } + + s.logger.Info("stopping telemetry server...", "address", s.config.Address) + return s.server.Shutdown(ctx) +} + +func (s *Server[T]) metricsHandler(w http.ResponseWriter, r *http.Request) { + format := strings.TrimSpace(r.FormValue("format")) + + // errorResponse defines the attributes of a JSON error response. + type errorResponse struct { + Code int `json:"code,omitempty"` + Error string `json:"error"` + } + + gr, err := s.metrics.Gather(format) + if err != nil { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusBadRequest) + bz, err := json.Marshal(errorResponse{Code: 400, Error: fmt.Sprintf("failed to gather metrics: %s", err)}) + if err != nil { + return + } + _, _ = w.Write(bz) + + return + } + + w.Header().Set("Content-Type", gr.ContentType) + _, _ = w.Write(gr.Metrics) } diff --git a/server/v2/appmanager/appmanager.go b/server/v2/appmanager/appmanager.go index e367c7d8fbfe..6a5f96ec5fa9 100644 --- a/server/v2/appmanager/appmanager.go +++ b/server/v2/appmanager/appmanager.go @@ -43,25 +43,19 @@ func (a AppManager[T]) InitGenesis( initGenesisJSON []byte, txDecoder transaction.Codec[T], ) (*server.BlockResponse, corestore.WriterMap, error) { - v, zeroState, err := a.db.StateLatest() - if err != nil { - return nil, nil, fmt.Errorf("unable to get latest state: %w", err) - } - if v != 0 { // TODO: genesis state may be > 0, we need to set version on store - return nil, nil, errors.New("cannot init genesis on non-zero state") - } - var genTxs []T - genesisState, err := a.stf.RunWithCtx(ctx, zeroState, func(ctx context.Context) error { - return a.initGenesis(ctx, bytes.NewBuffer(initGenesisJSON), func(jsonTx json.RawMessage) error { + genesisState, err := a.initGenesis( + ctx, + bytes.NewBuffer(initGenesisJSON), + func(jsonTx json.RawMessage) error { genTx, err := txDecoder.DecodeJSON(jsonTx) if err != nil { return fmt.Errorf("failed to decode genesis transaction: %w", err) } genTxs = append(genTxs, genTx) return nil - }) - }) + }, + ) if err != nil { return nil, nil, fmt.Errorf("failed to import genesis state: %w", err) } @@ -89,29 +83,11 @@ func (a AppManager[T]) InitGenesis( // ExportGenesis exports the genesis state of the application. func (a AppManager[T]) ExportGenesis(ctx context.Context, version uint64) ([]byte, error) { - zeroState, err := a.db.StateAt(version) - if err != nil { - return nil, fmt.Errorf("unable to get latest state: %w", err) - } - - bz := make([]byte, 0) - _, err = a.stf.RunWithCtx(ctx, zeroState, func(ctx context.Context) error { - if a.exportGenesis == nil { - return errors.New("export genesis function not set") - } - - bz, err = a.exportGenesis(ctx, version) - if err != nil { - return fmt.Errorf("failed to export genesis state: %w", err) - } - - return nil - }) - if err != nil { - return nil, fmt.Errorf("failed to export genesis state: %w", err) + if a.exportGenesis == nil { + return nil, errors.New("export genesis function not set") } - return bz, nil + return a.exportGenesis(ctx, version) } func (a AppManager[T]) DeliverBlock( @@ -180,10 +156,6 @@ func (a AppManager[T]) Query(ctx context.Context, version uint64, request transa // QueryWithState executes a query with the provided state. This allows to process a query // independently of the db state. For example, it can be used to process a query with temporary // and uncommitted state -func (a AppManager[T]) QueryWithState( - ctx context.Context, - state corestore.ReaderMap, - request transaction.Msg, -) (transaction.Msg, error) { +func (a AppManager[T]) QueryWithState(ctx context.Context, state corestore.ReaderMap, request transaction.Msg) (transaction.Msg, error) { return a.stf.Query(ctx, state, a.config.QueryGasLimit, request) } diff --git a/server/v2/appmanager/genesis.go b/server/v2/appmanager/genesis.go index 8acad003b694..989ae442a9b9 100644 --- a/server/v2/appmanager/genesis.go +++ b/server/v2/appmanager/genesis.go @@ -4,11 +4,25 @@ import ( "context" "encoding/json" "io" + + "cosmossdk.io/core/store" ) type ( // ExportGenesis is a function type that represents the export of the genesis state. ExportGenesis func(ctx context.Context, version uint64) ([]byte, error) - // InitGenesis is a function type that represents the initialization of the genesis state. - InitGenesis func(ctx context.Context, src io.Reader, txHandler func(json.RawMessage) error) error + + // InitGenesis is a function that will run at application genesis, it will be called with + // the following arguments: + // - ctx: the context of the genesis operation + // - src: the source containing the raw genesis state + // - txHandler: a function capable of decoding a json tx, will be run for each genesis + // transaction + // + // It must return a map of the dirty state after the genesis operation. + InitGenesis func( + ctx context.Context, + src io.Reader, + txHandler func(json.RawMessage) error, + ) (store.WriterMap, error) ) diff --git a/server/v2/appmanager/go.mod b/server/v2/appmanager/go.mod index 8b53ae415a3e..110213b868b9 100644 --- a/server/v2/appmanager/go.mod +++ b/server/v2/appmanager/go.mod @@ -2,4 +2,6 @@ module cosmossdk.io/server/v2/appmanager go 1.23 -require cosmossdk.io/core v1.0.0-alpha.2 +require cosmossdk.io/core v1.0.0-alpha.3 + +require cosmossdk.io/schema v0.3.0 // indirect diff --git a/server/v2/appmanager/go.sum b/server/v2/appmanager/go.sum index 7277ab9d958a..e5d225b85b5e 100644 --- a/server/v2/appmanager/go.sum +++ b/server/v2/appmanager/go.sum @@ -1,2 +1,4 @@ -cosmossdk.io/core v1.0.0-alpha.2 h1:epU0Xwces4Rgl5bMhHHkXGaGDcyucNGlC/JDH+Suckg= -cosmossdk.io/core v1.0.0-alpha.2/go.mod h1:abgLjeFLhtuKIYZWSPlVUgQBrKObO7ULV35KYfexE90= +cosmossdk.io/core v1.0.0-alpha.3 h1:pnxaYAas7llXgVz1lM7X6De74nWrhNKnB3yMKe4OUUA= +cosmossdk.io/core v1.0.0-alpha.3/go.mod h1:3u9cWq1FAVtiiCrDPpo4LhR+9V6k/ycSG4/Y/tREWCY= +cosmossdk.io/schema v0.3.0 h1:01lcaM4trhzZ1HQTfTV8z6Ma1GziOZ/YmdzBN3F720c= +cosmossdk.io/schema v0.3.0/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= diff --git a/server/v2/appmanager/types.go b/server/v2/appmanager/types.go index 149f190f353e..1e769c13ff9c 100644 --- a/server/v2/appmanager/types.go +++ b/server/v2/appmanager/types.go @@ -40,12 +40,4 @@ type StateTransitionFunction[T transaction.Tx] interface { gasLimit uint64, req transaction.Msg, ) (transaction.Msg, error) - - // RunWithCtx executes the provided closure within a context. - // TODO: remove - RunWithCtx( - ctx context.Context, - state store.ReaderMap, - closure func(ctx context.Context) error, - ) (store.WriterMap, error) } diff --git a/server/v2/cometbft/abci.go b/server/v2/cometbft/abci.go index 06c1e43e5ecb..cbcf387168a2 100644 --- a/server/v2/cometbft/abci.go +++ b/server/v2/cometbft/abci.go @@ -5,20 +5,27 @@ import ( "crypto/sha256" "errors" "fmt" + "strings" + "sync" "sync/atomic" abci "github.com/cometbft/cometbft/abci/types" abciproto "github.com/cometbft/cometbft/api/cometbft/abci/v1" gogoproto "github.com/cosmos/gogoproto/proto" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + "google.golang.org/protobuf/reflect/protoregistry" + "cosmossdk.io/collections" + appmodulev2 "cosmossdk.io/core/appmodule/v2" "cosmossdk.io/core/comet" corecontext "cosmossdk.io/core/context" "cosmossdk.io/core/event" "cosmossdk.io/core/server" "cosmossdk.io/core/store" "cosmossdk.io/core/transaction" - errorsmod "cosmossdk.io/errors" + errorsmod "cosmossdk.io/errors/v2" "cosmossdk.io/log" + "cosmossdk.io/schema/appdata" "cosmossdk.io/server/v2/appmanager" "cosmossdk.io/server/v2/cometbft/client/grpc/cmtservice" "cosmossdk.io/server/v2/cometbft/handlers" @@ -33,15 +40,15 @@ import ( var _ abci.Application = (*Consensus[transaction.Tx])(nil) type Consensus[T transaction.Tx] struct { - logger log.Logger - appName, version string - consensusAuthority string // Set by the application to grant authority to the consensus engine to send messages to the consensus module - app *appmanager.AppManager[T] - txCodec transaction.Codec[T] - store types.Store - streaming streaming.Manager - snapshotManager *snapshots.Manager - mempool mempool.Mempool[T] + logger log.Logger + appName, version string + app *appmanager.AppManager[T] + txCodec transaction.Codec[T] + store types.Store + streaming streaming.Manager + listener *appdata.Listener + snapshotManager *snapshots.Manager + mempool mempool.Mempool[T] cfg Config indexedEvents map[string]struct{} @@ -57,21 +64,22 @@ type Consensus[T transaction.Tx] struct { processProposalHandler handlers.ProcessHandler[T] verifyVoteExt handlers.VerifyVoteExtensionhandler extendVote handlers.ExtendVoteHandler + checkTxHandler handlers.CheckTxHandler[T] addrPeerFilter types.PeerFilter // filter peers by address and port idPeerFilter types.PeerFilter // filter peers by node ID - grpcMethodsMap map[string]func() transaction.Msg // maps gRPC method to message creator func + queryHandlersMap map[string]appmodulev2.Handler + getProtoRegistry func() (*protoregistry.Files, error) } func NewConsensus[T transaction.Tx]( logger log.Logger, appName string, - consensusAuthority string, // TODO remove app *appmanager.AppManager[T], mp mempool.Mempool[T], indexedEvents map[string]struct{}, - gRPCMethodsMap map[string]func() transaction.Msg, + queryHandlersMap map[string]appmodulev2.Handler, store types.Store, cfg Config, txCodec transaction.Codec[T], @@ -80,8 +88,6 @@ func NewConsensus[T transaction.Tx]( return &Consensus[T]{ appName: appName, version: getCometBFTServerVersion(), - consensusAuthority: consensusAuthority, - grpcMethodsMap: gRPCMethodsMap, app: app, cfg: cfg, store: store, @@ -98,6 +104,8 @@ func NewConsensus[T transaction.Tx]( chainID: chainId, indexedEvents: indexedEvents, initialHeight: 0, + queryHandlersMap: queryHandlersMap, + getProtoRegistry: sync.OnceValues(func() (*protoregistry.Files, error) { return gogoproto.MergedRegistry() }), } } @@ -106,6 +114,11 @@ func (c *Consensus[T]) SetStreamingManager(sm streaming.Manager) { c.streaming = sm } +// SetListener sets the listener for the consensus module. +func (c *Consensus[T]) SetListener(l *appdata.Listener) { + c.listener = l +} + // RegisterSnapshotExtensions registers the given extensions with the consensus module's snapshot manager. // It allows additional snapshotter implementations to be used for creating and restoring snapshots. func (c *Consensus[T]) RegisterSnapshotExtensions(extensions ...snapshots.ExtensionSnapshotter) error { @@ -124,22 +137,35 @@ func (c *Consensus[T]) CheckTx(ctx context.Context, req *abciproto.CheckTxReques return nil, err } - resp, err := c.app.ValidateTx(ctx, decodedTx) - if err != nil { - return nil, err - } + if c.checkTxHandler == nil { + resp, err := c.app.ValidateTx(ctx, decodedTx) + // we do not want to return a cometbft error, but a check tx response with the error + if err != nil && !errors.Is(err, resp.Error) { + return nil, err + } - cometResp := &abciproto.CheckTxResponse{ - Code: resp.Code, - GasWanted: uint64ToInt64(resp.GasWanted), - GasUsed: uint64ToInt64(resp.GasUsed), - Events: intoABCIEvents(resp.Events, c.indexedEvents), - } - if resp.Error != nil { - cometResp.Code = 1 - cometResp.Log = resp.Error.Error() + events, err := intoABCIEvents(resp.Events, c.indexedEvents) + if err != nil { + return nil, err + } + + cometResp := &abciproto.CheckTxResponse{ + Code: 0, + GasWanted: uint64ToInt64(resp.GasWanted), + GasUsed: uint64ToInt64(resp.GasUsed), + Events: events, + } + if resp.Error != nil { + space, code, log := errorsmod.ABCIInfo(resp.Error, c.cfg.AppTomlConfig.Trace) + cometResp.Code = code + cometResp.Codespace = space + cometResp.Log = log + } + + return cometResp, nil } - return cometResp, nil + + return c.checkTxHandler(c.app.ValidateTx) } // Info implements types.Application. @@ -155,7 +181,7 @@ func (c *Consensus[T]) Info(ctx context.Context, _ *abciproto.InfoRequest) (*abc cp, err := c.GetConsensusParams(ctx) // if the consensus params are not found, we set the app version to 0 // in the case that the start version is > 0 - if cp == nil || errors.Is(err, errors.New("collections: not found")) { + if cp == nil || errors.Is(err, collections.ErrNotFound) { appVersion = 0 } else if err != nil { return nil, err @@ -184,23 +210,9 @@ func (c *Consensus[T]) Info(ctx context.Context, _ *abciproto.InfoRequest) (*abc // Query implements types.Application. // It is called by cometbft to query application state. func (c *Consensus[T]) Query(ctx context.Context, req *abciproto.QueryRequest) (resp *abciproto.QueryResponse, err error) { - // check if it's a gRPC method - makeGRPCRequest, isGRPC := c.grpcMethodsMap[req.Path] + resp, isGRPC, err := c.maybeRunGRPCQuery(ctx, req) if isGRPC { - protoRequest := makeGRPCRequest() - err = gogoproto.Unmarshal(req.Data, protoRequest) // TODO: use codec - if err != nil { - return nil, fmt.Errorf("unable to decode gRPC request with path %s from ABCI.Query: %w", req.Path, err) - } - res, err := c.app.Query(ctx, uint64(req.Height), protoRequest) - if err != nil { - resp := queryResult(err) - resp.Height = req.Height - return resp, err - - } - - return queryResponse(res, req.Height) + return resp, err } // this error most probably means that we can't handle it with a proto message, so @@ -231,6 +243,50 @@ func (c *Consensus[T]) Query(ctx context.Context, req *abciproto.QueryRequest) ( return resp, nil } +func (c *Consensus[T]) maybeRunGRPCQuery(ctx context.Context, req *abci.QueryRequest) (resp *abciproto.QueryResponse, isGRPC bool, err error) { + // if this fails then we cannot serve queries anymore + registry, err := c.getProtoRegistry() + if err != nil { + return nil, false, err + } + + path := strings.TrimPrefix(req.Path, "/") + pathFullName := protoreflect.FullName(strings.ReplaceAll(path, "/", ".")) + + // in order to check if it's a gRPC query we ensure that there's a descriptor + // for the path, if such descriptor exists, and it is a method descriptor + // then we assume this is a gRPC query. + desc, err := registry.FindDescriptorByName(pathFullName) + if err != nil { + return nil, false, err + } + + md, isGRPC := desc.(protoreflect.MethodDescriptor) + if !isGRPC { + return nil, false, nil + } + + handler, found := c.queryHandlersMap[string(md.Input().FullName())] + if !found { + return nil, true, fmt.Errorf("no query handler found for %s", req.Path) + } + protoRequest := handler.MakeMsg() + err = gogoproto.Unmarshal(req.Data, protoRequest) // TODO: use codec + if err != nil { + return nil, true, fmt.Errorf("unable to decode gRPC request with path %s from ABCI.Query: %w", req.Path, err) + } + res, err := c.app.Query(ctx, uint64(req.Height), protoRequest) + if err != nil { + resp := QueryResult(err, c.cfg.AppTomlConfig.Trace) + resp.Height = req.Height + return resp, true, err + + } + + resp, err = queryResponse(res, req.Height) + return resp, isGRPC, err +} + // InitChain implements types.Application. func (c *Consensus[T]) InitChain(ctx context.Context, req *abciproto.InitChainRequest) (*abciproto.InitChainResponse, error) { c.logger.Info("InitChain", "initialHeight", req.InitialHeight, "chainID", req.ChainId) @@ -246,7 +302,6 @@ func (c *Consensus[T]) InitChain(ctx context.Context, req *abciproto.InitChainRe if req.ConsensusParams != nil { ctx = context.WithValue(ctx, corecontext.CometParamsInitInfoKey, &consensustypes.MsgUpdateParams{ - Authority: c.consensusAuthority, Block: req.ConsensusParams.Block, Evidence: req.ConsensusParams.Evidence, Validator: req.ConsensusParams.Validator, @@ -282,10 +337,10 @@ func (c *Consensus[T]) InitChain(ctx context.Context, req *abciproto.InitChainRe return nil, fmt.Errorf("genesis state init failure: %w", err) } - // TODO necessary? where should this WARN live if it all. helpful for testing for _, txRes := range blockresponse.TxResults { - if txRes.Error != nil { - c.logger.Warn("genesis tx failed", "code", txRes.Code, "error", txRes.Error) + if err := txRes.Error; err != nil { + space, code, log := errorsmod.ABCIInfo(err, c.cfg.AppTomlConfig.Trace) + c.logger.Warn("genesis tx failed", "codespace", space, "code", code, "log", log) } } @@ -471,9 +526,10 @@ func (c *Consensus[T]) FinalizeBlock( } // remove txs from the mempool - err = c.mempool.Remove(decodedTxs) - if err != nil { - return nil, fmt.Errorf("unable to remove txs: %w", err) + for _, tx := range decodedTxs { + if err = c.mempool.Remove(tx); err != nil { + return nil, fmt.Errorf("unable to remove tx: %w", err) + } } c.lastCommittedHeight.Store(req.Height) @@ -483,7 +539,7 @@ func (c *Consensus[T]) FinalizeBlock( return nil, err } - return finalizeBlockResponse(resp, cp, appHash, c.indexedEvents) + return finalizeBlockResponse(resp, cp, appHash, c.indexedEvents, c.cfg.AppTomlConfig.Trace) } // Commit implements types.Application. diff --git a/server/v2/cometbft/abci_test.go b/server/v2/cometbft/abci_test.go index 0a4f1b16f975..3af3fbec8f29 100644 --- a/server/v2/cometbft/abci_test.go +++ b/server/v2/cometbft/abci_test.go @@ -334,9 +334,6 @@ func TestConsensus_ExtendVote(t *testing.T) { Block: &v1.BlockParams{ MaxGas: 5000000, }, - Abci: &v1.ABCIParams{ - VoteExtensionsEnableHeight: 2, - }, Feature: &v1.FeatureParams{ VoteExtensionsEnableHeight: &gogotypes.Int64Value{Value: 2}, }, @@ -376,9 +373,6 @@ func TestConsensus_VerifyVoteExtension(t *testing.T) { Block: &v1.BlockParams{ MaxGas: 5000000, }, - Abci: &v1.ABCIParams{ - VoteExtensionsEnableHeight: 2, - }, Feature: &v1.FeatureParams{ VoteExtensionsEnableHeight: &gogotypes.Int64Value{Value: 2}, }, @@ -537,6 +531,7 @@ func TestConsensus_ProcessProposal_With_Handler(t *testing.T) { Height: 1, Txs: [][]byte{mockTx.Bytes(), append(mockTx.Bytes(), []byte("bad")...), mockTx.Bytes(), mockTx.Bytes()}, }) + require.NoError(t, err) require.Equal(t, res.Status, abciproto.PROCESS_PROPOSAL_STATUS_REJECT) } @@ -642,9 +637,6 @@ func setUpConsensus(t *testing.T, gasLimit uint64, mempool mempool.Mempool[mock. Block: &v1.BlockParams{ MaxGas: 300000, }, - Abci: &v1.ABCIParams{ - VoteExtensionsEnableHeight: 2, - }, Feature: &v1.FeatureParams{ VoteExtensionsEnableHeight: &gogotypes.Int64Value{Value: 2}, }, @@ -686,15 +678,17 @@ func setUpConsensus(t *testing.T, gasLimit uint64, mempool mempool.Mempool[mock. ValidateTxGasLimit: gasLimit, QueryGasLimit: gasLimit, SimulationGasLimit: gasLimit, - InitGenesis: func(ctx context.Context, src io.Reader, txHandler func(json.RawMessage) error) error { - return nil + InitGenesis: func(ctx context.Context, src io.Reader, txHandler func(json.RawMessage) error) (store.WriterMap, error) { + _, st, err := mockStore.StateLatest() + require.NoError(t, err) + return branch.DefaultNewWriterMap(st), nil }, } am, err := b.Build() require.NoError(t, err) - return NewConsensus[mock.Tx](log.NewNopLogger(), "testing-app", "authority", am, mempool, map[string]struct{}{}, nil, mockStore, Config{AppTomlConfig: DefaultAppTomlConfig()}, mock.TxCodec{}, "test") + return NewConsensus[mock.Tx](log.NewNopLogger(), "testing-app", am, mempool, map[string]struct{}{}, nil, mockStore, Config{AppTomlConfig: DefaultAppTomlConfig()}, mock.TxCodec{}, "test") } // Check target version same with store's latest version diff --git a/server/v2/cometbft/commands.go b/server/v2/cometbft/commands.go index 787bd2c7810f..d1bb2f257245 100644 --- a/server/v2/cometbft/commands.go +++ b/server/v2/cometbft/commands.go @@ -106,15 +106,13 @@ func ShowValidatorCmd() *cobra.Command { return err } - cmd.Println(sdkPK) // TODO: figure out if we need the codec here or not, see below - - // clientCtx := client.GetClientContextFromCmd(cmd) - // bz, err := clientCtx.Codec.MarshalInterfaceJSON(sdkPK) - // if err != nil { - // return err - // } + clientCtx := client.GetClientContextFromCmd(cmd) + bz, err := clientCtx.Codec.MarshalInterfaceJSON(sdkPK) + if err != nil { + return err + } - // cmd.Println(string(bz)) + cmd.Println(string(bz)) return nil }, } diff --git a/server/v2/cometbft/config.go b/server/v2/cometbft/config.go index 81f3aeb33354..4525e7563c27 100644 --- a/server/v2/cometbft/config.go +++ b/server/v2/cometbft/config.go @@ -2,6 +2,8 @@ package cometbft import ( cmtcfg "github.com/cometbft/cometbft/config" + + "cosmossdk.io/server/v2/cometbft/mempool" ) // Config is the configuration for the CometBFT application @@ -20,6 +22,7 @@ func DefaultAppTomlConfig() *AppTomlConfig { Transport: "socket", Trace: false, Standalone: false, + Mempool: mempool.DefaultConfig(), } } @@ -32,6 +35,9 @@ type AppTomlConfig struct { Transport string `mapstructure:"transport" toml:"transport" comment:"transport defines the CometBFT RPC server transport protocol: socket, grpc"` Trace bool `mapstructure:"trace" toml:"trace" comment:"trace enables the CometBFT RPC server to output trace information about its internal operations."` Standalone bool `mapstructure:"standalone" toml:"standalone" comment:"standalone starts the application without the CometBFT node. The node should be started separately."` + + // Sub configs + Mempool mempool.Config `mapstructure:"mempool" toml:"mempool" comment:"mempool defines the configuration for the SDK built-in app-side mempool implementations."` } // CfgOption is a function that allows to overwrite the default server configuration. diff --git a/server/v2/cometbft/flags.go b/server/v2/cometbft/flags.go index 55fa0a14e771..216755f9885b 100644 --- a/server/v2/cometbft/flags.go +++ b/server/v2/cometbft/flags.go @@ -51,10 +51,11 @@ func prefix(f string) string { // Server flags var ( - Standalone = prefix("standalone") - FlagAddress = prefix("address") - FlagTransport = prefix("transport") - FlagHaltHeight = prefix("halt-height") - FlagHaltTime = prefix("halt-time") - FlagTrace = prefix("trace") + Standalone = prefix("standalone") + FlagAddress = prefix("address") + FlagTransport = prefix("transport") + FlagHaltHeight = prefix("halt-height") + FlagHaltTime = prefix("halt-time") + FlagTrace = prefix("trace") + FlagMempoolMaxTxs = prefix("mempool.max-txs") ) diff --git a/server/v2/cometbft/go.mod b/server/v2/cometbft/go.mod index 334ec6e05049..e92a3221ada5 100644 --- a/server/v2/cometbft/go.mod +++ b/server/v2/cometbft/go.mod @@ -4,7 +4,6 @@ go 1.23.1 replace ( cosmossdk.io/api => ../../../api - cosmossdk.io/core/testing => ../../../core/testing cosmossdk.io/server/v2 => ../ cosmossdk.io/server/v2/appmanager => ../appmanager cosmossdk.io/server/v2/stf => ../stf @@ -18,10 +17,12 @@ replace ( ) require ( - cosmossdk.io/api v0.7.5 - cosmossdk.io/core v1.0.0-alpha.2 - cosmossdk.io/errors v1.0.1 + cosmossdk.io/api v0.7.6 + cosmossdk.io/collections v0.4.0 + cosmossdk.io/core v1.0.0-alpha.4 + cosmossdk.io/errors/v2 v2.0.0-20240731132947-df72853b3ca5 cosmossdk.io/log v1.4.1 + cosmossdk.io/schema v0.3.1-0.20240930054013-7c6e0388a3f9 cosmossdk.io/server/v2 v2.0.0-00010101000000-000000000000 cosmossdk.io/server/v2/appmanager v0.0.0-20240802110823-cffeedff643d cosmossdk.io/server/v2/stf v0.0.0-20240708142107-25e99c54bac1 @@ -35,18 +36,17 @@ require ( github.com/spf13/cobra v1.8.1 github.com/spf13/pflag v1.0.5 github.com/stretchr/testify v1.9.0 + google.golang.org/protobuf v1.34.2 sigs.k8s.io/yaml v1.4.0 ) require ( buf.build/gen/go/cometbft/cometbft/protocolbuffers/go v1.34.2-20240701160653-fedbb9acfd2f.2 // indirect buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.34.2-20240130113600-88ef6483f90f.2 // indirect - cosmossdk.io/collections v0.4.0 // indirect - cosmossdk.io/core/testing v0.0.0-00010101000000-000000000000 // indirect + cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29 // indirect cosmossdk.io/depinject v1.0.0 // indirect - cosmossdk.io/errors/v2 v2.0.0-20240731132947-df72853b3ca5 // indirect + cosmossdk.io/errors v1.0.1 // indirect cosmossdk.io/math v1.3.0 // indirect - cosmossdk.io/schema v0.2.0 // indirect cosmossdk.io/store v1.1.1-0.20240418092142-896cdf1971bc // indirect cosmossdk.io/x/bank v0.0.0-20240226161501-23359a0b6d91 // indirect cosmossdk.io/x/staking v0.0.0-00010101000000-000000000000 // indirect @@ -116,7 +116,7 @@ require ( github.com/hashicorp/hcl v1.0.0 // indirect github.com/hashicorp/yamux v0.1.1 // indirect github.com/hdevalence/ed25519consensus v0.2.0 // indirect - github.com/huandu/skiplist v1.2.0 // indirect + github.com/huandu/skiplist v1.2.1 // indirect github.com/iancoleman/strcase v0.3.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jmhodges/levigo v1.0.0 // indirect @@ -140,9 +140,9 @@ require ( github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/client_golang v1.20.3 // indirect + github.com/prometheus/client_golang v1.20.4 // indirect github.com/prometheus/client_model v0.6.1 // indirect - github.com/prometheus/common v0.59.1 // indirect + github.com/prometheus/common v0.60.0 // indirect github.com/prometheus/procfs v0.15.1 // indirect github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect github.com/rogpeppe/go-internal v1.12.0 // indirect @@ -177,10 +177,9 @@ require ( golang.org/x/text v0.18.0 // indirect golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect - google.golang.org/grpc v1.66.2 // indirect - google.golang.org/protobuf v1.34.2 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f // indirect + google.golang.org/grpc v1.67.1 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect gotest.tools/v3 v3.5.1 // indirect diff --git a/server/v2/cometbft/go.sum b/server/v2/cometbft/go.sum index 9d4fcef2a2e2..ea29392600d8 100644 --- a/server/v2/cometbft/go.sum +++ b/server/v2/cometbft/go.sum @@ -6,8 +6,10 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cosmossdk.io/collections v0.4.0 h1:PFmwj2W8szgpD5nOd8GWH6AbYNi1f2J6akWXJ7P5t9s= cosmossdk.io/collections v0.4.0/go.mod h1:oa5lUING2dP+gdDquow+QjlF45eL1t4TJDypgGd+tv0= -cosmossdk.io/core v1.0.0-alpha.2 h1:epU0Xwces4Rgl5bMhHHkXGaGDcyucNGlC/JDH+Suckg= -cosmossdk.io/core v1.0.0-alpha.2/go.mod h1:abgLjeFLhtuKIYZWSPlVUgQBrKObO7ULV35KYfexE90= +cosmossdk.io/core v1.0.0-alpha.4 h1:9iuroT9ejDYETCsGkzkvs/wAY/5UFl7nCIINFRxyMJY= +cosmossdk.io/core v1.0.0-alpha.4/go.mod h1:3u9cWq1FAVtiiCrDPpo4LhR+9V6k/ycSG4/Y/tREWCY= +cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29 h1:NxxUo0GMJUbIuVg0R70e3cbn9eFTEuMr7ev1AFvypdY= +cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29/go.mod h1:8s2tPeJtSiQuoyPmr2Ag7meikonISO4Fv4MoO8+ORrs= cosmossdk.io/depinject v1.0.0 h1:dQaTu6+O6askNXO06+jyeUAnF2/ssKwrrszP9t5q050= cosmossdk.io/depinject v1.0.0/go.mod h1:zxK/h3HgHoA/eJVtiSsoaRaRA2D5U4cJ5thIG4ssbB8= cosmossdk.io/errors v1.0.1 h1:bzu+Kcr0kS/1DuPBtUFdWjzLqyUuCiyHjyJB6srBV/0= @@ -18,8 +20,8 @@ cosmossdk.io/log v1.4.1 h1:wKdjfDRbDyZRuWa8M+9nuvpVYxrEOwbD/CA8hvhU8QM= cosmossdk.io/log v1.4.1/go.mod h1:k08v0Pyq+gCP6phvdI6RCGhLf/r425UT6Rk/m+o74rU= cosmossdk.io/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE= cosmossdk.io/math v1.3.0/go.mod h1:vnRTxewy+M7BtXBNFybkuhSH4WfedVAAnERHgVFhp3k= -cosmossdk.io/schema v0.2.0 h1:UH5CR1DqUq8yP+5Np8PbvG4YX0zAUsTN2Qk6yThmfMk= -cosmossdk.io/schema v0.2.0/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= +cosmossdk.io/schema v0.3.1-0.20240930054013-7c6e0388a3f9 h1:DmOoS/1PeY6Ih0hAVlJ69kLMUrLV+TCbfICrZtB1vdU= +cosmossdk.io/schema v0.3.1-0.20240930054013-7c6e0388a3f9/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMbk2FiG/kXiLl8BRyzTWDw7gX/Hz7Dd5eDMs= @@ -294,8 +296,8 @@ github.com/hdevalence/ed25519consensus v0.2.0/go.mod h1:w3BHWjwJbFU29IRHL1Iqkw3s github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/huandu/go-assert v1.1.5 h1:fjemmA7sSfYHJD7CUqs9qTwwfdNAx7/j2/ZlHXzNB3c= github.com/huandu/go-assert v1.1.5/go.mod h1:yOLvuqZwmcHIC5rIzrBhT7D3Q9c3GFnd0JrPVhn/06U= -github.com/huandu/skiplist v1.2.0 h1:gox56QD77HzSC0w+Ws3MH3iie755GBJU1OER3h5VsYw= -github.com/huandu/skiplist v1.2.0/go.mod h1:7v3iFjLcSAzO4fN5B8dvebvo/qsfumiLiDXMrPiHF9w= +github.com/huandu/skiplist v1.2.1 h1:dTi93MgjwErA/8idWTzIw4Y1kZsMWx35fmI2c8Rij7w= +github.com/huandu/skiplist v1.2.1/go.mod h1:7v3iFjLcSAzO4fN5B8dvebvo/qsfumiLiDXMrPiHF9w= github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI= github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= @@ -406,8 +408,8 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= -github.com/prometheus/client_golang v1.20.3 h1:oPksm4K8B+Vt35tUhw6GbSNSgVlVSBH0qELP/7u83l4= -github.com/prometheus/client_golang v1.20.3/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_golang v1.20.4 h1:Tgh3Yr67PaOv/uTqloMsCEdeuFTatm5zIq5+qNN23vI= +github.com/prometheus/client_golang v1.20.4/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -416,8 +418,8 @@ github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= -github.com/prometheus/common v0.59.1 h1:LXb1quJHWm1P6wq/U824uxYi4Sg0oGvNeUm1z5dJoX0= -github.com/prometheus/common v0.59.1/go.mod h1:GpWM7dewqmVYcd7SmRaiWVe9SSqjf0UrwnYnpEZNuT0= +github.com/prometheus/common v0.60.0 h1:+V9PAREWNvJMAuJ1x1BaWl9dewMW4YrHZQbx0sJNllA= +github.com/prometheus/common v0.60.0/go.mod h1:h0LYf1R1deLSKtD4Vdg8gy4RuOvENW2J/h19V5NADQw= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/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= @@ -636,10 +638,10 @@ google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEY google.golang.org/genproto v0.0.0-20220314164441-57ef72a4c106/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E= google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de h1:F6qOa9AZTYJXOUEr4jDysRDLrm4PHePlge4v4TGAlxY= google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:VUhTRKeHn9wwcdrk73nvdC9gF178Tzhmt/qyaFcPLSo= -google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 h1:+rdxYoE3E5htTEWIe15GlN6IfvbURM//Jt0mmkmm6ZU= -google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117/go.mod h1:OimBR/bc1wPO9iV4NC2bpyjy3VnAwZh5EBPQdtaE5oo= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:pPJltXNxVzT4pK9yD8vR9X75DaWYYmLGMsEvBfFQZzQ= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= +google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 h1:wKguEg1hsxI2/L3hUYrpo1RVi48K+uTyzKqprwLXsb8= +google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142/go.mod h1:d6be+8HhtEtucleCbxpPW9PA9XwISACu8nvpPqF0BVo= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f h1:cUMEy+8oS78BWIH9OWazBkzbr090Od9tWBNtZHkOhf0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= @@ -650,8 +652,8 @@ google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= -google.golang.org/grpc v1.66.2 h1:3QdXkuq3Bkh7w+ywLdLvM56cmGvQHUMZpiCzt6Rqaoo= -google.golang.org/grpc v1.66.2/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y= +google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E= +google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= 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= diff --git a/server/v2/cometbft/handlers/defaults.go b/server/v2/cometbft/handlers/defaults.go index 18ad38669c9c..d8f43bb2fd25 100644 --- a/server/v2/cometbft/handlers/defaults.go +++ b/server/v2/cometbft/handlers/defaults.go @@ -79,7 +79,7 @@ func (h *DefaultProposalHandler[T]) PrepareHandler() PrepareHandler[T] { // check again. _, err := app.ValidateTx(ctx, memTx) if err != nil { - err := h.mempool.Remove([]T{memTx}) + err := h.mempool.Remove(memTx) if err != nil && !errors.Is(err, mempool.ErrTxNotFound) { return nil, err } diff --git a/server/v2/cometbft/handlers/handlers.go b/server/v2/cometbft/handlers/handlers.go index 9008490f6a44..015594f469f7 100644 --- a/server/v2/cometbft/handlers/handlers.go +++ b/server/v2/cometbft/handlers/handlers.go @@ -5,6 +5,7 @@ import ( abci "github.com/cometbft/cometbft/api/cometbft/abci/v1" + "cosmossdk.io/core/server" "cosmossdk.io/core/store" "cosmossdk.io/core/transaction" ) @@ -27,4 +28,7 @@ type ( // It takes a context, a store reader map, and a request to extend a vote. // It returns a response to extend the vote and an error if any. ExtendVoteHandler func(context.Context, store.ReaderMap, *abci.ExtendVoteRequest) (*abci.ExtendVoteResponse, error) + + // CheckTxHandler is a function type that handles the execution of a transaction. + CheckTxHandler[T transaction.Tx] func(func(ctx context.Context, tx T) (server.TxResult, error)) (*abci.CheckTxResponse, error) ) diff --git a/server/v2/cometbft/internal/mock/mock_mempool.go b/server/v2/cometbft/internal/mock/mock_mempool.go index 89d51e955fae..401b12d60139 100644 --- a/server/v2/cometbft/internal/mock/mock_mempool.go +++ b/server/v2/cometbft/internal/mock/mock_mempool.go @@ -15,5 +15,6 @@ type MockMempool[T transaction.Tx] struct{} func (MockMempool[T]) Insert(context.Context, T) error { return nil } func (MockMempool[T]) Select(context.Context, []T) mempool.Iterator[T] { return nil } +func (MockMempool[T]) SelectBy(context.Context, []T, func(T) bool) {} func (MockMempool[T]) CountTx() int { return 0 } -func (MockMempool[T]) Remove([]T) error { return nil } +func (MockMempool[T]) Remove(T) error { return nil } diff --git a/server/v2/cometbft/mempool/config.go b/server/v2/cometbft/mempool/config.go index 38de18844107..e07d6a6e7167 100644 --- a/server/v2/cometbft/mempool/config.go +++ b/server/v2/cometbft/mempool/config.go @@ -1,11 +1,16 @@ package mempool -// Config defines the configurations for the SDK built-in app-side mempool -// implementations. +var DefaultMaxTx = -1 + +// Config defines the configurations for the SDK built-in app-side mempool implementations. type Config struct { - // MaxTxs defines the behavior of the mempool. A negative value indicates - // the mempool is disabled entirely, zero indicates that the mempool is - // unbounded in how many txs it may contain, and a positive value indicates - // the maximum amount of txs it may contain. - MaxTxs int `mapstructure:"max-txs"` + // MaxTxs defines the maximum number of transactions that can be in the mempool. + MaxTxs int `mapstructure:"max-txs" toml:"max-txs" comment:"max-txs defines the maximum number of transactions that can be in the mempool. A value of 0 indicates an unbounded mempool, a negative value disables the app-side mempool."` +} + +// DefaultConfig returns a default configuration for the SDK built-in app-side mempool implementations. +func DefaultConfig() Config { + return Config{ + MaxTxs: DefaultMaxTx, + } } diff --git a/server/v2/cometbft/mempool/doc.go b/server/v2/cometbft/mempool/doc.go index f9857f3a9fae..eb6c72aced18 100644 --- a/server/v2/cometbft/mempool/doc.go +++ b/server/v2/cometbft/mempool/doc.go @@ -1,6 +1,2 @@ -/* -The mempool package defines a few mempool services which can be used in conjunction with your consensus implementation - -*/ - +// Package mempool defines a few mempool services which can be used in conjunction with your consensus implementation. package mempool diff --git a/server/v2/cometbft/mempool/mempool.go b/server/v2/cometbft/mempool/mempool.go index 3cb81c871508..0b28c5a2b922 100644 --- a/server/v2/cometbft/mempool/mempool.go +++ b/server/v2/cometbft/mempool/mempool.go @@ -19,13 +19,18 @@ type Mempool[T transaction.Tx] interface { Insert(context.Context, T) error // Select returns an Iterator over the app-side mempool. If txs are specified, - // then they shall be incorporated into the Iterator. The Iterator must be - // closed by the caller. + // then they shall be incorporated into the Iterator. The Iterator is not thread-safe to use. Select(context.Context, []T) Iterator[T] + // SelectBy use callback to iterate over the mempool, it's thread-safe to use. + SelectBy(context.Context, []T, func(T) bool) + + // CountTx returns the number of transactions currently in the mempool. + CountTx() int + // Remove attempts to remove a transaction from the mempool, returning an error // upon failure. - Remove([]T) error + Remove(T) error } // Iterator defines an app-side mempool iterator interface that is as minimal as diff --git a/server/v2/cometbft/mempool/noop.go b/server/v2/cometbft/mempool/noop.go index 86cea55e2c53..3d3e4feab2da 100644 --- a/server/v2/cometbft/mempool/noop.go +++ b/server/v2/cometbft/mempool/noop.go @@ -4,9 +4,14 @@ import ( "context" "cosmossdk.io/core/transaction" + + sdk "github.com/cosmos/cosmos-sdk/types" ) -var _ Mempool[transaction.Tx] = (*NoOpMempool[transaction.Tx])(nil) +var ( + _ Mempool[sdk.Tx] = (*NoOpMempool[sdk.Tx])(nil) // verify interface at compile time + _ Mempool[transaction.Tx] = (*NoOpMempool[transaction.Tx])(nil) +) // NoOpMempool defines a no-op mempool. Transactions are completely discarded and // ignored when BaseApp interacts with the mempool. @@ -16,7 +21,8 @@ var _ Mempool[transaction.Tx] = (*NoOpMempool[transaction.Tx])(nil) // is FIFO-ordered by default. type NoOpMempool[T transaction.Tx] struct{} -func (NoOpMempool[T]) Insert(context.Context, T) error { return nil } -func (NoOpMempool[T]) Select(context.Context, []T) Iterator[T] { return nil } -func (NoOpMempool[T]) CountTx() int { return 0 } -func (NoOpMempool[T]) Remove([]T) error { return nil } +func (NoOpMempool[T]) Insert(context.Context, T) error { return nil } +func (NoOpMempool[T]) Select(context.Context, []T) Iterator[T] { return nil } +func (NoOpMempool[T]) SelectBy(context.Context, []T, func(T) bool) {} +func (NoOpMempool[T]) CountTx() int { return 0 } +func (NoOpMempool[T]) Remove(T) error { return nil } diff --git a/server/v2/cometbft/options.go b/server/v2/cometbft/options.go index 1e0a389882e0..d5aa4872fff2 100644 --- a/server/v2/cometbft/options.go +++ b/server/v2/cometbft/options.go @@ -1,6 +1,9 @@ package cometbft import ( + cmtcrypto "github.com/cometbft/cometbft/crypto" + cmted22519 "github.com/cometbft/cometbft/crypto/ed25519" + "cosmossdk.io/core/transaction" "cosmossdk.io/server/v2/cometbft/handlers" "cosmossdk.io/server/v2/cometbft/mempool" @@ -8,15 +11,20 @@ import ( "cosmossdk.io/store/v2/snapshots" ) +type keyGenF = func() (cmtcrypto.PrivKey, error) + // ServerOptions defines the options for the CometBFT server. +// When an option takes a map[string]any, it can access the app.tom's cometbft section and the config.toml config. type ServerOptions[T transaction.Tx] struct { - Mempool mempool.Mempool[T] PrepareProposalHandler handlers.PrepareHandler[T] ProcessProposalHandler handlers.ProcessHandler[T] + CheckTxHandler handlers.CheckTxHandler[T] VerifyVoteExtensionHandler handlers.VerifyVoteExtensionhandler ExtendVoteHandler handlers.ExtendVoteHandler + KeygenF keyGenF - SnapshotOptions snapshots.SnapshotOptions + Mempool func(cfg map[string]any) mempool.Mempool[T] + SnapshotOptions func(cfg map[string]any) snapshots.SnapshotOptions AddrPeerFilter types.PeerFilter // filter peers by address and port IdPeerFilter types.PeerFilter // filter peers by node ID @@ -26,13 +34,15 @@ type ServerOptions[T transaction.Tx] struct { // It defaults to a NoOpMempool and NoOp handlers. func DefaultServerOptions[T transaction.Tx]() ServerOptions[T] { return ServerOptions[T]{ - Mempool: mempool.NoOpMempool[T]{}, PrepareProposalHandler: handlers.NoOpPrepareProposal[T](), ProcessProposalHandler: handlers.NoOpProcessProposal[T](), + CheckTxHandler: nil, VerifyVoteExtensionHandler: handlers.NoOpVerifyVoteExtensionHandler(), ExtendVoteHandler: handlers.NoOpExtendVote(), - SnapshotOptions: snapshots.NewSnapshotOptions(0, 0), + Mempool: func(cfg map[string]any) mempool.Mempool[T] { return mempool.NoOpMempool[T]{} }, + SnapshotOptions: func(cfg map[string]any) snapshots.SnapshotOptions { return snapshots.NewSnapshotOptions(0, 0) }, AddrPeerFilter: nil, IdPeerFilter: nil, + KeygenF: func() (cmtcrypto.PrivKey, error) { return cmted22519.GenPrivKey(), nil }, } } diff --git a/server/v2/cometbft/query.go b/server/v2/cometbft/query.go index 912338ff79f3..8a624f56fc32 100644 --- a/server/v2/cometbft/query.go +++ b/server/v2/cometbft/query.go @@ -7,7 +7,7 @@ import ( abci "github.com/cometbft/cometbft/api/cometbft/abci/v1" crypto "github.com/cometbft/cometbft/api/cometbft/crypto/v1" - errorsmod "cosmossdk.io/errors" + errorsmod "cosmossdk.io/errors/v2" "cosmossdk.io/server/v2/cometbft/types" cometerrors "cosmossdk.io/server/v2/cometbft/types/errors" ) diff --git a/server/v2/cometbft/server.go b/server/v2/cometbft/server.go index 26cd99ff97cd..b15f5695cf94 100644 --- a/server/v2/cometbft/server.go +++ b/server/v2/cometbft/server.go @@ -11,8 +11,6 @@ import ( abciserver "github.com/cometbft/cometbft/abci/server" cmtcmd "github.com/cometbft/cometbft/cmd/cometbft/commands" cmtcfg "github.com/cometbft/cometbft/config" - cmtcrypto "github.com/cometbft/cometbft/crypto" - cmted25519 "github.com/cometbft/cometbft/crypto/ed25519" "github.com/cometbft/cometbft/node" "github.com/cometbft/cometbft/p2p" pvm "github.com/cometbft/cometbft/privval" @@ -24,6 +22,7 @@ import ( "cosmossdk.io/log" serverv2 "cosmossdk.io/server/v2" cometlog "cosmossdk.io/server/v2/cometbft/log" + "cosmossdk.io/server/v2/cometbft/mempool" "cosmossdk.io/server/v2/cometbft/types" "cosmossdk.io/store/v2/snapshots" @@ -103,11 +102,10 @@ func (s *CometBFTServer[T]) Init(appI serverv2.AppI[T], cfg map[string]any, logg consensus := NewConsensus( s.logger, appI.Name(), - appI.GetConsensusAuthority(), appI.GetAppManager(), - s.serverOptions.Mempool, + s.serverOptions.Mempool(cfg), indexEvents, - appI.GetGPRCMethodsToMessageMap(), + appI.GetQueryHandlers(), store, s.config, s.initTxCodec, @@ -115,6 +113,7 @@ func (s *CometBFTServer[T]) Init(appI serverv2.AppI[T], cfg map[string]any, logg ) consensus.prepareProposalHandler = s.serverOptions.PrepareProposalHandler consensus.processProposalHandler = s.serverOptions.ProcessProposalHandler + consensus.checkTxHandler = s.serverOptions.CheckTxHandler consensus.verifyVoteExt = s.serverOptions.VerifyVoteExtensionHandler consensus.extendVote = s.serverOptions.ExtendVoteHandler consensus.addrPeerFilter = s.serverOptions.AddrPeerFilter @@ -127,7 +126,7 @@ func (s *CometBFTServer[T]) Init(appI serverv2.AppI[T], cfg map[string]any, logg if err != nil { return err } - consensus.snapshotManager = snapshots.NewManager(snapshotStore, s.serverOptions.SnapshotOptions, sc, ss, nil, s.logger) + consensus.snapshotManager = snapshots.NewManager(snapshotStore, s.serverOptions.SnapshotOptions(cfg), sc, ss, nil, s.logger) s.Consensus = consensus @@ -159,9 +158,7 @@ func (s *CometBFTServer[T]) Start(ctx context.Context) error { pv, err := pvm.LoadOrGenFilePV( s.config.ConfigTomlConfig.PrivValidatorKeyFile(), s.config.ConfigTomlConfig.PrivValidatorStateFile(), - func() (cmtcrypto.PrivKey, error) { - return cmted25519.GenPrivKey(), nil - }, + s.serverOptions.KeygenF, ) if err != nil { return err @@ -240,6 +237,7 @@ func (s *CometBFTServer[T]) StartCmdFlags() *pflag.FlagSet { flags.Uint64(FlagHaltTime, 0, "Minimum block time (in Unix seconds) at which to gracefully halt the chain and shutdown the node") flags.Bool(FlagTrace, false, "Provide full stack traces for errors in ABCI Log") flags.Bool(Standalone, false, "Run app without CometBFT") + flags.Int(FlagMempoolMaxTxs, mempool.DefaultMaxTx, "Sets MaxTx value for the app-side mempool") // add comet flags, we use an empty command to avoid duplicating CometBFT's AddNodeFlags. // we can then merge the flag sets. @@ -274,7 +272,7 @@ func (s *CometBFTServer[T]) CLICommands() serverv2.CLIConfig { // Config returns the (app.toml) server configuration. func (s *CometBFTServer[T]) Config() any { - if s.config.AppTomlConfig == nil || s.config.AppTomlConfig == (&AppTomlConfig{}) { + if s.config.AppTomlConfig == nil || s.config.AppTomlConfig.Address == "" { cfg := &Config{AppTomlConfig: DefaultAppTomlConfig()} // overwrite the default config with the provided options for _, opt := range s.cfgOptions { diff --git a/server/v2/cometbft/streaming.go b/server/v2/cometbft/streaming.go index 0c8af07aa547..65f52a002af1 100644 --- a/server/v2/cometbft/streaming.go +++ b/server/v2/cometbft/streaming.go @@ -6,6 +6,8 @@ import ( "cosmossdk.io/core/event" "cosmossdk.io/core/server" "cosmossdk.io/core/store" + errorsmod "cosmossdk.io/errors/v2" + "cosmossdk.io/schema/appdata" "cosmossdk.io/server/v2/streaming" ) @@ -21,20 +23,33 @@ func (c *Consensus[T]) streamDeliverBlockChanges( // convert txresults to streaming txresults streamingTxResults := make([]*streaming.ExecTxResult, len(txResults)) for i, txResult := range txResults { + space, code, log := errorsmod.ABCIInfo(txResult.Error, c.cfg.AppTomlConfig.Trace) + + events, err := streaming.IntoStreamingEvents(txResult.Events) + if err != nil { + return err + } + streamingTxResults[i] = &streaming.ExecTxResult{ - Code: txResult.Code, + Code: code, + Codespace: space, + Log: log, GasWanted: uint64ToInt64(txResult.GasWanted), GasUsed: uint64ToInt64(txResult.GasUsed), - Events: streaming.IntoStreamingEvents(txResult.Events), + Events: events, } } for _, streamingListener := range c.streaming.Listeners { + events, err := streaming.IntoStreamingEvents(events) + if err != nil { + return err + } if err := streamingListener.ListenDeliverBlock(ctx, streaming.ListenDeliverBlockRequest{ BlockHeight: height, Txs: txs, TxResults: streamingTxResults, - Events: streaming.IntoStreamingEvents(events), + Events: events, }); err != nil { c.logger.Error("ListenDeliverBlock listening hook failed", "height", height, "err", err) } @@ -43,6 +58,55 @@ func (c *Consensus[T]) streamDeliverBlockChanges( c.logger.Error("ListenStateChanges listening hook failed", "height", height, "err", err) } } + + if c.listener == nil { + return nil + } + // stream the StartBlockData to the listener. + if c.listener.StartBlock != nil { + if err := c.listener.StartBlock(appdata.StartBlockData{ + Height: uint64(height), + HeaderBytes: nil, // TODO: https://github.com/cosmos/cosmos-sdk/issues/22009 + HeaderJSON: nil, // TODO: https://github.com/cosmos/cosmos-sdk/issues/22009 + }); err != nil { + return err + } + } + // stream the TxData to the listener. + if c.listener.OnTx != nil { + for i, tx := range txs { + if err := c.listener.OnTx(appdata.TxData{ + TxIndex: int32(i), + Bytes: func() ([]byte, error) { return tx, nil }, + JSON: nil, // TODO: https://github.com/cosmos/cosmos-sdk/issues/22009 + }); err != nil { + return err + } + } + } + // stream the EventData to the listener. + if c.listener.OnEvent != nil { + if err := c.listener.OnEvent(appdata.EventData{Events: events}); err != nil { + return err + } + } + // stream the KVPairData to the listener. + if c.listener.OnKVPair != nil { + if err := c.listener.OnKVPair(appdata.KVPairData{Updates: stateChanges}); err != nil { + return err + } + } + // stream the CommitData to the listener. + if c.listener.Commit != nil { + if completionCallback, err := c.listener.Commit(appdata.CommitData{}); err != nil { + return err + } else if completionCallback != nil { + if err := completionCallback(); err != nil { + return err + } + } + } + return nil } diff --git a/server/v2/cometbft/types/errors/errors.go b/server/v2/cometbft/types/errors/errors.go index 380c176ff306..e60f32338358 100644 --- a/server/v2/cometbft/types/errors/errors.go +++ b/server/v2/cometbft/types/errors/errors.go @@ -1,7 +1,7 @@ package errors import ( - errorsmod "cosmossdk.io/errors" + errorsmod "cosmossdk.io/errors/v2" ) // RootCodespace is the codespace for all errors defined in this package diff --git a/server/v2/cometbft/utils.go b/server/v2/cometbft/utils.go index 6aaf1b5401d6..2b1052bd1953 100644 --- a/server/v2/cometbft/utils.go +++ b/server/v2/cometbft/utils.go @@ -18,7 +18,7 @@ import ( "cosmossdk.io/core/event" "cosmossdk.io/core/server" "cosmossdk.io/core/transaction" - errorsmod "cosmossdk.io/errors" + errorsmod "cosmossdk.io/errors/v2" consensus "cosmossdk.io/x/consensus/types" sdk "github.com/cosmos/cosmos-sdk/types" @@ -70,12 +70,23 @@ func finalizeBlockResponse( cp *cmtproto.ConsensusParams, appHash []byte, indexSet map[string]struct{}, + debug bool, ) (*abci.FinalizeBlockResponse, error) { allEvents := append(in.BeginBlockEvents, in.EndBlockEvents...) + events, err := intoABCIEvents(allEvents, indexSet) + if err != nil { + return nil, err + } + + txResults, err := intoABCITxResults(in.TxResults, indexSet, debug) + if err != nil { + return nil, err + } + resp := &abci.FinalizeBlockResponse{ - Events: intoABCIEvents(allEvents, indexSet), - TxResults: intoABCITxResults(in.TxResults, indexSet), + Events: events, + TxResults: txResults, ValidatorUpdates: intoABCIValidatorUpdates(in.ValidatorUpdates), AppHash: appHash, ConsensusParamUpdates: cp, @@ -97,42 +108,40 @@ func intoABCIValidatorUpdates(updates []appmodulev2.ValidatorUpdate) []abci.Vali return valsetUpdates } -func intoABCITxResults(results []server.TxResult, indexSet map[string]struct{}) []*abci.ExecTxResult { +func intoABCITxResults(results []server.TxResult, indexSet map[string]struct{}, debug bool) ([]*abci.ExecTxResult, error) { res := make([]*abci.ExecTxResult, len(results)) for i := range results { - if results[i].Error != nil { - space, code, log := errorsmod.ABCIInfo(results[i].Error, true) - res[i] = &abci.ExecTxResult{ - Codespace: space, - Code: code, - Log: log, - } - - continue + events, err := intoABCIEvents(results[i].Events, indexSet) + if err != nil { + return nil, err } res[i] = responseExecTxResultWithEvents( results[i].Error, results[i].GasWanted, results[i].GasUsed, - intoABCIEvents(results[i].Events, indexSet), - false, + events, + debug, ) } - return res + return res, nil } -func intoABCIEvents(events []event.Event, indexSet map[string]struct{}) []abci.Event { +func intoABCIEvents(events []event.Event, indexSet map[string]struct{}) ([]abci.Event, error) { indexAll := len(indexSet) == 0 abciEvents := make([]abci.Event, len(events)) for i, e := range events { + attributes, err := e.Attributes() + if err != nil { + return nil, err + } abciEvents[i] = abci.Event{ Type: e.Type, - Attributes: make([]abci.EventAttribute, len(e.Attributes)), + Attributes: make([]abci.EventAttribute, len(attributes)), } - for j, attr := range e.Attributes { + for j, attr := range attributes { _, index := indexSet[fmt.Sprintf("%s.%s", e.Type, attr.Key)] abciEvents[i].Attributes[j] = abci.EventAttribute{ Key: attr.Key, @@ -141,19 +150,23 @@ func intoABCIEvents(events []event.Event, indexSet map[string]struct{}) []abci.E } } } - return abciEvents + return abciEvents, nil } func intoABCISimulationResponse(txRes server.TxResult, indexSet map[string]struct{}) ([]byte, error) { indexAll := len(indexSet) == 0 abciEvents := make([]abci.Event, len(txRes.Events)) for i, e := range txRes.Events { + attributes, err := e.Attributes() + if err != nil { + return nil, err + } abciEvents[i] = abci.Event{ Type: e.Type, - Attributes: make([]abci.EventAttribute, len(e.Attributes)), + Attributes: make([]abci.EventAttribute, len(attributes)), } - for j, attr := range e.Attributes { + for j, attr := range attributes { _, index := indexSet[fmt.Sprintf("%s.%s", e.Type, attr.Key)] abciEvents[i].Attributes[j] = abci.EventAttribute{ Key: attr.Key, @@ -366,10 +379,10 @@ func (c *Consensus[T]) GetBlockRetentionHeight(cp *cmtproto.ConsensusParams, com func (c *Consensus[T]) checkHalt(height int64, time time.Time) error { var halt bool switch { - case c.cfg.AppTomlConfig.HaltHeight > 0 && uint64(height) > c.cfg.AppTomlConfig.HaltHeight: + case c.cfg.AppTomlConfig.HaltHeight > 0 && uint64(height) >= c.cfg.AppTomlConfig.HaltHeight: halt = true - case c.cfg.AppTomlConfig.HaltTime > 0 && time.Unix() > int64(c.cfg.AppTomlConfig.HaltTime): + case c.cfg.AppTomlConfig.HaltTime > 0 && time.Unix() >= int64(c.cfg.AppTomlConfig.HaltTime): halt = true } @@ -387,14 +400,3 @@ func uint64ToInt64(u uint64) int64 { } return int64(u) } - -// queryResult returns a ResponseQuery from an error. It will try to parse ABCI -// info from the error. -func queryResult(err error) *abci.QueryResponse { - space, code, log := errorsmod.ABCIInfo(err, false) - return &abci.QueryResponse{ - Codespace: space, - Code: code, - Log: log, - } -} diff --git a/server/v2/commands.go b/server/v2/commands.go index 8651074f406f..da8e0ec6e537 100644 --- a/server/v2/commands.go +++ b/server/v2/commands.go @@ -38,14 +38,14 @@ func AddCommands[T transaction.Tx]( rootCmd *cobra.Command, newApp AppCreator[T], logger log.Logger, - serverCfg ServerConfig, + globalServerCfg ServerConfig, components ...ServerComponent[T], ) error { if len(components) == 0 { return errors.New("no components provided") } - server := NewServer(logger, serverCfg, components...) + server := NewServer(logger, globalServerCfg, components...) originalPersistentPreRunE := rootCmd.PersistentPreRunE rootCmd.PersistentPreRunE = func(cmd *cobra.Command, args []string) error { // set the default command outputs diff --git a/server/v2/config_test.go b/server/v2/config_test.go index 6577b81192fb..f69e2ed56769 100644 --- a/server/v2/config_test.go +++ b/server/v2/config_test.go @@ -20,8 +20,8 @@ func TestReadConfig(t *testing.T) { v, err := serverv2.ReadConfig(configPath) require.NoError(t, err) - require.Equal(t, v.GetString("grpc.address"), grpc.DefaultConfig().Address) - require.Equal(t, v.GetString("store.app-db-backend"), store.DefaultConfig().AppDBBackend) + require.Equal(t, v.GetString(grpc.FlagAddress), grpc.DefaultConfig().Address) + require.Equal(t, v.GetString(store.FlagAppDBBackend), store.DefaultConfig().AppDBBackend) } func TestUnmarshalSubConfig(t *testing.T) { diff --git a/server/v2/go.mod b/server/v2/go.mod index dbb1d151c343..220989a6186e 100644 --- a/server/v2/go.mod +++ b/server/v2/go.mod @@ -4,7 +4,6 @@ go 1.23 replace ( cosmossdk.io/api => ../../api - cosmossdk.io/core/testing => ../../core/testing cosmossdk.io/server/v2/appmanager => ./appmanager cosmossdk.io/server/v2/stf => ./stf cosmossdk.io/store/v2 => ../../store/v2 @@ -13,9 +12,9 @@ replace ( ) require ( - cosmossdk.io/api v0.7.5 - cosmossdk.io/core v1.0.0-alpha.2 - cosmossdk.io/core/testing v0.0.0-00010101000000-000000000000 + cosmossdk.io/api v0.7.6 + cosmossdk.io/core v1.0.0-alpha.4 + cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29 cosmossdk.io/log v1.4.1 cosmossdk.io/server/v2/appmanager v0.0.0-00010101000000-000000000000 cosmossdk.io/store/v2 v2.0.0-00010101000000-000000000000 @@ -23,27 +22,27 @@ require ( github.com/cosmos/gogogateway v1.2.0 github.com/cosmos/gogoproto v1.7.0 github.com/golang/protobuf v1.5.4 - github.com/gorilla/mux v1.8.1 github.com/grpc-ecosystem/grpc-gateway v1.16.0 github.com/hashicorp/go-hclog v1.6.3 github.com/hashicorp/go-metrics v0.5.3 github.com/hashicorp/go-plugin v1.6.1 github.com/mitchellh/mapstructure v1.5.0 github.com/pelletier/go-toml/v2 v2.2.2 - github.com/prometheus/client_golang v1.20.3 - github.com/prometheus/common v0.59.1 + github.com/prometheus/client_golang v1.20.4 + github.com/prometheus/common v0.60.0 github.com/rs/zerolog v1.33.0 github.com/spf13/cobra v1.8.1 github.com/spf13/pflag v1.0.5 github.com/spf13/viper v1.19.0 github.com/stretchr/testify v1.9.0 golang.org/x/sync v0.8.0 - google.golang.org/grpc v1.66.2 + google.golang.org/grpc v1.67.1 google.golang.org/protobuf v1.34.2 ) require ( cosmossdk.io/errors/v2 v2.0.0-20240731132947-df72853b3ca5 // indirect + cosmossdk.io/schema v0.3.0 // indirect github.com/DataDog/datadog-go v4.8.3+incompatible // indirect github.com/DataDog/zstd v1.5.5 // indirect github.com/Microsoft/go-winio v0.6.1 // indirect @@ -106,8 +105,8 @@ require ( golang.org/x/text v0.18.0 // indirect golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/server/v2/go.sum b/server/v2/go.sum index 5c55e95c520e..842232d93dbb 100644 --- a/server/v2/go.sum +++ b/server/v2/go.sum @@ -1,11 +1,15 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cosmossdk.io/core v1.0.0-alpha.2 h1:epU0Xwces4Rgl5bMhHHkXGaGDcyucNGlC/JDH+Suckg= -cosmossdk.io/core v1.0.0-alpha.2/go.mod h1:abgLjeFLhtuKIYZWSPlVUgQBrKObO7ULV35KYfexE90= +cosmossdk.io/core v1.0.0-alpha.4 h1:9iuroT9ejDYETCsGkzkvs/wAY/5UFl7nCIINFRxyMJY= +cosmossdk.io/core v1.0.0-alpha.4/go.mod h1:3u9cWq1FAVtiiCrDPpo4LhR+9V6k/ycSG4/Y/tREWCY= +cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29 h1:NxxUo0GMJUbIuVg0R70e3cbn9eFTEuMr7ev1AFvypdY= +cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29/go.mod h1:8s2tPeJtSiQuoyPmr2Ag7meikonISO4Fv4MoO8+ORrs= cosmossdk.io/errors/v2 v2.0.0-20240731132947-df72853b3ca5 h1:IQNdY2kB+k+1OM2DvqFG1+UgeU1JzZrWtwuWzI3ZfwA= cosmossdk.io/errors/v2 v2.0.0-20240731132947-df72853b3ca5/go.mod h1:0CuYKkFHxc1vw2JC+t21THBCALJVROrWVR/3PQ1urpc= cosmossdk.io/log v1.4.1 h1:wKdjfDRbDyZRuWa8M+9nuvpVYxrEOwbD/CA8hvhU8QM= cosmossdk.io/log v1.4.1/go.mod h1:k08v0Pyq+gCP6phvdI6RCGhLf/r425UT6Rk/m+o74rU= +cosmossdk.io/schema v0.3.0 h1:01lcaM4trhzZ1HQTfTV8z6Ma1GziOZ/YmdzBN3F720c= +cosmossdk.io/schema v0.3.0/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/DataDog/datadog-go v4.8.3+incompatible h1:fNGaYSuObuQb5nzeTQqowRAd9bpDIRRV4/gUtIBjh8Q= @@ -146,8 +150,6 @@ github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= -github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= @@ -256,8 +258,8 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= -github.com/prometheus/client_golang v1.20.3 h1:oPksm4K8B+Vt35tUhw6GbSNSgVlVSBH0qELP/7u83l4= -github.com/prometheus/client_golang v1.20.3/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_golang v1.20.4 h1:Tgh3Yr67PaOv/uTqloMsCEdeuFTatm5zIq5+qNN23vI= +github.com/prometheus/client_golang v1.20.4/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -266,8 +268,8 @@ github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= -github.com/prometheus/common v0.59.1 h1:LXb1quJHWm1P6wq/U824uxYi4Sg0oGvNeUm1z5dJoX0= -github.com/prometheus/common v0.59.1/go.mod h1:GpWM7dewqmVYcd7SmRaiWVe9SSqjf0UrwnYnpEZNuT0= +github.com/prometheus/common v0.60.0 h1:+V9PAREWNvJMAuJ1x1BaWl9dewMW4YrHZQbx0sJNllA= +github.com/prometheus/common v0.60.0/go.mod h1:h0LYf1R1deLSKtD4Vdg8gy4RuOvENW2J/h19V5NADQw= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/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= @@ -446,10 +448,10 @@ google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEY google.golang.org/genproto v0.0.0-20220314164441-57ef72a4c106/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E= google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de h1:F6qOa9AZTYJXOUEr4jDysRDLrm4PHePlge4v4TGAlxY= google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:VUhTRKeHn9wwcdrk73nvdC9gF178Tzhmt/qyaFcPLSo= -google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 h1:+rdxYoE3E5htTEWIe15GlN6IfvbURM//Jt0mmkmm6ZU= -google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117/go.mod h1:OimBR/bc1wPO9iV4NC2bpyjy3VnAwZh5EBPQdtaE5oo= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:pPJltXNxVzT4pK9yD8vR9X75DaWYYmLGMsEvBfFQZzQ= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= +google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 h1:wKguEg1hsxI2/L3hUYrpo1RVi48K+uTyzKqprwLXsb8= +google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142/go.mod h1:d6be+8HhtEtucleCbxpPW9PA9XwISACu8nvpPqF0BVo= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f h1:cUMEy+8oS78BWIH9OWazBkzbr090Od9tWBNtZHkOhf0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= @@ -458,8 +460,8 @@ google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTp google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= -google.golang.org/grpc v1.66.2 h1:3QdXkuq3Bkh7w+ywLdLvM56cmGvQHUMZpiCzt6Rqaoo= -google.golang.org/grpc v1.66.2/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y= +google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E= +google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= 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= diff --git a/server/v2/server.go b/server/v2/server.go index d1062618ab60..7ee91e649982 100644 --- a/server/v2/server.go +++ b/server/v2/server.go @@ -89,7 +89,6 @@ func (s *Server[T]) Start(ctx context.Context) error { g, ctx := errgroup.WithContext(ctx) for _, mod := range s.components { - mod := mod g.Go(func() error { return mod.Start(ctx) }) @@ -110,7 +109,6 @@ func (s *Server[T]) Stop(ctx context.Context) error { g, ctx := errgroup.WithContext(ctx) for _, mod := range s.components { - mod := mod g.Go(func() error { return mod.Stop(ctx) }) @@ -198,7 +196,6 @@ func (s *Server[T]) Init(appI AppI[T], cfg map[string]any, logger log.Logger) er var components []ServerComponent[T] for _, mod := range s.components { - mod := mod if err := mod.Init(appI, cfg, logger); err != nil { return err } diff --git a/server/v2/server_test.go b/server/v2/server_test.go index e84bcd598890..97afa40fdaa9 100644 --- a/server/v2/server_test.go +++ b/server/v2/server_test.go @@ -11,6 +11,7 @@ import ( "github.com/spf13/viper" "github.com/stretchr/testify/require" + appmodulev2 "cosmossdk.io/core/appmodule/v2" coreserver "cosmossdk.io/core/server" "cosmossdk.io/core/transaction" "cosmossdk.io/log" @@ -35,8 +36,8 @@ type mockApp[T transaction.Tx] struct { serverv2.AppI[T] } -func (*mockApp[T]) GetGPRCMethodsToMessageMap() map[string]func() gogoproto.Message { - return map[string]func() gogoproto.Message{} +func (*mockApp[T]) GetQueryHandlers() map[string]appmodulev2.Handler { + return map[string]appmodulev2.Handler{} } func (*mockApp[T]) GetAppManager() *appmanager.AppManager[T] { diff --git a/server/v2/stf/branch/changeset.go b/server/v2/stf/branch/changeset.go index c409b1b7becf..07a29345aee7 100644 --- a/server/v2/stf/branch/changeset.go +++ b/server/v2/stf/branch/changeset.go @@ -99,7 +99,7 @@ type memIterator struct { } // newMemIterator creates a new memory iterator for a given range of keys in a B-tree. -// The iterator starts at the specified start key and ends at the specified end key. +// The iterator creates a copy then starts at the specified start key and ends at the specified end key. // The `tree` parameter is the B-tree to iterate over. // The `ascending` parameter determines the direction of iteration. // If `ascending` is true, the iterator will iterate in ascending order. @@ -111,7 +111,7 @@ type memIterator struct { // The `valid` field of the iterator indicates whether the iterator is positioned at a valid key. // The `start` and `end` fields of the iterator store the start and end keys respectively. func newMemIterator(start, end []byte, tree *btree.BTreeG[item], ascending bool) *memIterator { - iter := tree.Iter() + iter := tree.Copy().Iter() var valid bool if ascending { if start != nil { @@ -207,6 +207,9 @@ func (mi *memIterator) keyInRange(key []byte) bool { if !mi.ascending && mi.start != nil && bytes.Compare(key, mi.start) < 0 { return false } + if !mi.ascending && mi.end != nil && bytes.Compare(key, mi.end) >= 0 { + return false + } return true } diff --git a/server/v2/stf/branch/changeset_test.go b/server/v2/stf/branch/changeset_test.go index 6a820c241c3d..fb7464915168 100644 --- a/server/v2/stf/branch/changeset_test.go +++ b/server/v2/stf/branch/changeset_test.go @@ -4,7 +4,7 @@ import ( "testing" ) -func Test_memIterator(t *testing.T) { +func TestMemIteratorWithWriteToRebalance(t *testing.T) { t.Run("iter is invalid after close", func(t *testing.T) { cs := newChangeSet() for i := byte(0); i < 32; i++ { @@ -26,3 +26,62 @@ func Test_memIterator(t *testing.T) { } }) } + +func TestKeyInRange(t *testing.T) { + specs := map[string]struct { + mi *memIterator + src []byte + exp bool + }{ + "equal start": { + mi: &memIterator{ascending: true, start: []byte{0}, end: []byte{2}}, + src: []byte{0}, + exp: true, + }, + "equal end": { + mi: &memIterator{ascending: true, start: []byte{0}, end: []byte{2}}, + src: []byte{2}, + exp: false, + }, + "between": { + mi: &memIterator{ascending: true, start: []byte{0}, end: []byte{2}}, + src: []byte{1}, + exp: true, + }, + "equal start - open end": { + mi: &memIterator{ascending: true, start: []byte{0}}, + src: []byte{0}, + exp: true, + }, + "greater start - open end": { + mi: &memIterator{ascending: true, start: []byte{0}}, + src: []byte{2}, + exp: true, + }, + "equal end - open start": { + mi: &memIterator{ascending: true, end: []byte{2}}, + src: []byte{2}, + exp: false, + }, + "smaller end - open start": { + mi: &memIterator{ascending: true, end: []byte{2}}, + src: []byte{1}, + exp: true, + }, + } + for name, spec := range specs { + for _, asc := range []bool{true, false} { + order := "asc_" + if !asc { + order = "desc_" + } + t.Run(order+name, func(t *testing.T) { + spec.mi.ascending = asc + got := spec.mi.keyInRange(spec.src) + if spec.exp != got { + t.Errorf("expected %v, got %v", spec.exp, got) + } + }) + } + } +} diff --git a/server/v2/stf/core_event_service.go b/server/v2/stf/core_event_service.go index 7a294fc77960..9f9b48080cae 100644 --- a/server/v2/stf/core_event_service.go +++ b/server/v2/stf/core_event_service.go @@ -81,6 +81,6 @@ func TypedEventToEvent(tev transaction.Msg) (event.Event, error) { return event.Event{ Type: evtType, - Attributes: attrs, + Attributes: func() ([]event.Attribute, error) { return attrs, nil }, }, nil } diff --git a/server/v2/stf/go.mod b/server/v2/stf/go.mod index 86eaec4d343a..06f5ca471a13 100644 --- a/server/v2/stf/go.mod +++ b/server/v2/stf/go.mod @@ -3,7 +3,8 @@ module cosmossdk.io/server/v2/stf go 1.23 require ( - cosmossdk.io/core v1.0.0-alpha.2 + cosmossdk.io/core v1.0.0-alpha.4 + cosmossdk.io/schema v0.3.0 github.com/cosmos/gogoproto v1.7.0 github.com/tidwall/btree v1.7.0 ) diff --git a/server/v2/stf/go.sum b/server/v2/stf/go.sum index 4fda4ea50d7d..95ab31efba84 100644 --- a/server/v2/stf/go.sum +++ b/server/v2/stf/go.sum @@ -1,5 +1,7 @@ -cosmossdk.io/core v1.0.0-alpha.2 h1:epU0Xwces4Rgl5bMhHHkXGaGDcyucNGlC/JDH+Suckg= -cosmossdk.io/core v1.0.0-alpha.2/go.mod h1:abgLjeFLhtuKIYZWSPlVUgQBrKObO7ULV35KYfexE90= +cosmossdk.io/core v1.0.0-alpha.4 h1:9iuroT9ejDYETCsGkzkvs/wAY/5UFl7nCIINFRxyMJY= +cosmossdk.io/core v1.0.0-alpha.4/go.mod h1:3u9cWq1FAVtiiCrDPpo4LhR+9V6k/ycSG4/Y/tREWCY= +cosmossdk.io/schema v0.3.0 h1:01lcaM4trhzZ1HQTfTV8z6Ma1GziOZ/YmdzBN3F720c= +cosmossdk.io/schema v0.3.0/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= github.com/cosmos/gogoproto v1.7.0 h1:79USr0oyXAbxg3rspGh/m4SWNyoz/GLaAh0QlCe2fro= github.com/cosmos/gogoproto v1.7.0/go.mod h1:yWChEv5IUEYURQasfyBW5ffkMHR/90hiHgbNgrtp4j0= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= diff --git a/server/v2/stf/stf.go b/server/v2/stf/stf.go index e32a8f33293e..f665aaf3c6e9 100644 --- a/server/v2/stf/stf.go +++ b/server/v2/stf/stf.go @@ -15,6 +15,7 @@ import ( "cosmossdk.io/core/server" "cosmossdk.io/core/store" "cosmossdk.io/core/transaction" + "cosmossdk.io/schema/appdata" stfgas "cosmossdk.io/server/v2/stf/gas" "cosmossdk.io/server/v2/stf/internal" ) @@ -56,11 +57,11 @@ func NewSTF[T transaction.Tx]( postTxExec func(ctx context.Context, tx T, success bool) error, branch func(store store.ReaderMap) store.WriterMap, ) (*STF[T], error) { - msgRouter, err := msgRouterBuilder.Build() + msgRouter, err := msgRouterBuilder.build() if err != nil { return nil, fmt.Errorf("build msg router: %w", err) } - queryRouter, err := queryRouterBuilder.Build() + queryRouter, err := queryRouterBuilder.build() if err != nil { return nil, fmt.Errorf("build query router: %w", err) } @@ -122,7 +123,6 @@ func (s STF[T]) DeliverBlock( // reset events exCtx.events = make([]event.Event, 0) - // begin block var beginBlockEvents []event.Event if !block.IsGenesis { @@ -146,7 +146,7 @@ func (s STF[T]) DeliverBlock( if err = isCtxCancelled(ctx); err != nil { return nil, nil, err } - txResults[i] = s.deliverTx(exCtx, newState, txBytes, transaction.ExecModeFinalize, hi) + txResults[i] = s.deliverTx(exCtx, newState, txBytes, transaction.ExecModeFinalize, hi, int32(i+1)) } // reset events exCtx.events = make([]event.Event, 0) @@ -172,6 +172,7 @@ func (s STF[T]) deliverTx( tx T, execMode transaction.ExecMode, hi header.Info, + txIndex int32, ) server.TxResult { // recover in the case of a panic var recoveryError error @@ -194,17 +195,32 @@ func (s STF[T]) deliverTx( Error: recoveryError, } } - validateGas, validationEvents, err := s.validateTx(ctx, state, gasLimit, tx, execMode) if err != nil { return server.TxResult{ Error: err, } } + events := make([]event.Event, 0) + // set the event indexes, set MsgIndex to 0 in validation events + for i, e := range validationEvents { + e.BlockStage = appdata.TxProcessingStage + e.TxIndex = txIndex + e.MsgIndex = 0 + e.EventIndex = int32(i + 1) + events = append(events, e) + } execResp, execGas, execEvents, err := s.execTx(ctx, state, gasLimit-validateGas, tx, execMode, hi) + // set the TxIndex in the exec events + for _, e := range execEvents { + e.BlockStage = appdata.TxProcessingStage + e.TxIndex = txIndex + events = append(events, e) + } + return server.TxResult{ - Events: append(validationEvents, execEvents...), + Events: events, GasUsed: execGas + validateGas, GasWanted: gasLimit, Resp: execResp, @@ -270,6 +286,12 @@ func (s STF[T]) execTx( if applyErr != nil { return nil, 0, nil, applyErr } + // set the event indexes, set MsgIndex to -1 in post tx events + for i := range postTxCtx.events { + postTxCtx.events[i].EventIndex = int32(i + 1) + postTxCtx.events[i].MsgIndex = -1 + } + return nil, gasUsed, postTxCtx.events, txErr } // tx execution went fine, now we use the same state to run the post tx exec handler, @@ -289,6 +311,11 @@ func (s STF[T]) execTx( if applyErr != nil { return nil, 0, nil, applyErr } + // set the event indexes, set MsgIndex to -1 in post tx events + for i := range postTxCtx.events { + postTxCtx.events[i].EventIndex = int32(i + 1) + postTxCtx.events[i].MsgIndex = -1 + } return msgsResp, gasUsed, append(runTxMsgsEvents, postTxCtx.events...), nil } @@ -315,17 +342,24 @@ func (s STF[T]) runTxMsgs( execCtx := s.makeContext(ctx, RuntimeIdentity, state, execMode) execCtx.setHeaderInfo(hi) execCtx.setGasLimit(gasLimit) + events := make([]event.Event, 0) for i, msg := range msgs { execCtx.sender = txSenders[i] + execCtx.events = make([]event.Event, 0) // reset events resp, err := s.msgRouter.Invoke(execCtx, msg) if err != nil { - return nil, 0, nil, fmt.Errorf("message execution at index %d failed: %w", i, err) + return nil, 0, nil, err // do not wrap the error or we lose the original error type } msgResps[i] = resp + for j, e := range execCtx.events { + e.MsgIndex = int32(i + 1) + e.EventIndex = int32(j + 1) + events = append(events, e) + } } consumed := execCtx.meter.Limit() - execCtx.meter.Remaining() - return msgResps, consumed, execCtx.events, nil + return msgResps, consumed, events, nil } // preBlock executes the pre block logic. @@ -338,11 +372,9 @@ func (s STF[T]) preBlock( return nil, err } - for i, e := range ctx.events { - ctx.events[i].Attributes = append( - e.Attributes, - event.Attribute{Key: "mode", Value: "PreBlock"}, - ) + for i := range ctx.events { + ctx.events[i].BlockStage = appdata.PreBlockStage + ctx.events[i].EventIndex = int32(i + 1) } return ctx.events, nil @@ -357,11 +389,9 @@ func (s STF[T]) beginBlock( return nil, err } - for i, e := range ctx.events { - ctx.events[i].Attributes = append( - e.Attributes, - event.Attribute{Key: "mode", Value: "BeginBlock"}, - ) + for i := range ctx.events { + ctx.events[i].BlockStage = appdata.BeginBlockStage + ctx.events[i].EventIndex = int32(i + 1) } return ctx.events, nil @@ -375,33 +405,30 @@ func (s STF[T]) endBlock( if err != nil { return nil, nil, err } - - events, valsetUpdates, err := s.validatorUpdates(ctx) + events := ctx.events + ctx.events = make([]event.Event, 0) // reset events + valsetUpdates, err := s.validatorUpdates(ctx) if err != nil { return nil, nil, err } - - ctx.events = append(ctx.events, events...) - - for i, e := range ctx.events { - ctx.events[i].Attributes = append( - e.Attributes, - event.Attribute{Key: "mode", Value: "BeginBlock"}, - ) + events = append(events, ctx.events...) + for i := range events { + events[i].BlockStage = appdata.EndBlockStage + events[i].EventIndex = int32(i + 1) } - return ctx.events, valsetUpdates, nil + return events, valsetUpdates, nil } // validatorUpdates returns the validator updates for the current block. It is called by endBlock after the endblock execution has concluded func (s STF[T]) validatorUpdates( ctx *executionContext, -) ([]event.Event, []appmodulev2.ValidatorUpdate, error) { +) ([]appmodulev2.ValidatorUpdate, error) { valSetUpdates, err := s.doValidatorUpdate(ctx) if err != nil { - return nil, nil, err + return nil, err } - return ctx.events, valSetUpdates, nil + return valSetUpdates, nil } // Simulate simulates the execution of a tx on the provided state. @@ -416,7 +443,7 @@ func (s STF[T]) Simulate( if err != nil { return server.TxResult{}, nil } - txr := s.deliverTx(ctx, simulationState, tx, internal.ExecModeSimulate, hi) + txr := s.deliverTx(ctx, simulationState, tx, internal.ExecModeSimulate, hi, 0) return txr, simulationState } @@ -456,19 +483,6 @@ func (s STF[T]) Query( return s.queryRouter.Invoke(queryCtx, req) } -// RunWithCtx is made to support genesis, if genesis was just the execution of messages instead -// of being something custom then we would not need this. PLEASE DO NOT USE. -// TODO: Remove -func (s STF[T]) RunWithCtx( - ctx context.Context, - state store.ReaderMap, - closure func(ctx context.Context) error, -) (store.WriterMap, error) { - branchedState := s.branchFn(state) - stfCtx := s.makeContext(ctx, nil, branchedState, internal.ExecModeFinalize) - return branchedState, closure(stfCtx) -} - // clone clones STF. func (s STF[T]) clone() STF[T] { return STF[T]{ diff --git a/server/v2/stf/stf_router.go b/server/v2/stf/stf_router.go index 0417788e4b78..86a27efc49e8 100644 --- a/server/v2/stf/stf_router.go +++ b/server/v2/stf/stf_router.go @@ -18,21 +18,21 @@ var ErrNoHandler = errors.New("no handler") // NewMsgRouterBuilder is a router that routes messages to their respective handlers. func NewMsgRouterBuilder() *MsgRouterBuilder { return &MsgRouterBuilder{ - handlers: make(map[string]appmodulev2.Handler), + handlers: make(map[string]appmodulev2.HandlerFunc), preHandlers: make(map[string][]appmodulev2.PreMsgHandler), postHandlers: make(map[string][]appmodulev2.PostMsgHandler), } } type MsgRouterBuilder struct { - handlers map[string]appmodulev2.Handler + handlers map[string]appmodulev2.HandlerFunc globalPreHandlers []appmodulev2.PreMsgHandler preHandlers map[string][]appmodulev2.PreMsgHandler postHandlers map[string][]appmodulev2.PostMsgHandler globalPostHandlers []appmodulev2.PostMsgHandler } -func (b *MsgRouterBuilder) RegisterHandler(msgType string, handler appmodulev2.Handler) error { +func (b *MsgRouterBuilder) RegisterHandler(msgType string, handler appmodulev2.HandlerFunc) error { // panic on override if _, ok := b.handlers[msgType]; ok { return fmt.Errorf("handler already registered: %s", msgType) @@ -62,8 +62,8 @@ func (b *MsgRouterBuilder) HandlerExists(msgType string) bool { return ok } -func (b *MsgRouterBuilder) Build() (coreRouterImpl, error) { - handlers := make(map[string]appmodulev2.Handler) +func (b *MsgRouterBuilder) build() (coreRouterImpl, error) { + handlers := make(map[string]appmodulev2.HandlerFunc) globalPreHandler := func(ctx context.Context, msg transaction.Msg) error { for _, h := range b.globalPreHandlers { @@ -100,12 +100,12 @@ func (b *MsgRouterBuilder) Build() (coreRouterImpl, error) { } func buildHandler( - handler appmodulev2.Handler, + handler appmodulev2.HandlerFunc, preHandlers []appmodulev2.PreMsgHandler, globalPreHandler appmodulev2.PreMsgHandler, postHandlers []appmodulev2.PostMsgHandler, globalPostHandler appmodulev2.PostMsgHandler, -) appmodulev2.Handler { +) appmodulev2.HandlerFunc { return func(ctx context.Context, msg transaction.Msg) (msgResp transaction.Msg, err error) { if len(preHandlers) != 0 { for _, preHandler := range preHandlers { @@ -144,7 +144,7 @@ var _ router.Service = (*coreRouterImpl)(nil) // coreRouterImpl implements the STF router for msg and query handlers. type coreRouterImpl struct { - handlers map[string]appmodulev2.Handler + handlers map[string]appmodulev2.HandlerFunc } func (r coreRouterImpl) CanInvoke(_ context.Context, typeURL string) error { diff --git a/server/v2/stf/stf_router_test.go b/server/v2/stf/stf_router_test.go index 0a63ae4b79d4..8e17b22fc805 100644 --- a/server/v2/stf/stf_router_test.go +++ b/server/v2/stf/stf_router_test.go @@ -18,7 +18,7 @@ func TestRouter(t *testing.T) { expectedResp := &gogotypes.StringValue{Value: "test"} - router := coreRouterImpl{handlers: map[string]appmodulev2.Handler{ + router := coreRouterImpl{handlers: map[string]appmodulev2.HandlerFunc{ gogoproto.MessageName(expectedMsg): func(ctx context.Context, gotMsg transaction.Msg) (msgResp transaction.Msg, err error) { if !reflect.DeepEqual(expectedMsg, gotMsg) { t.Errorf("expected message: %v, got: %v", expectedMsg, gotMsg) diff --git a/server/v2/stf/stf_test.go b/server/v2/stf/stf_test.go index 5fa4fce15b40..b4c84a62ff9a 100644 --- a/server/v2/stf/stf_test.go +++ b/server/v2/stf/stf_test.go @@ -11,15 +11,19 @@ import ( gogotypes "github.com/cosmos/gogoproto/types" appmodulev2 "cosmossdk.io/core/appmodule/v2" + "cosmossdk.io/core/event" coregas "cosmossdk.io/core/gas" "cosmossdk.io/core/server" "cosmossdk.io/core/store" "cosmossdk.io/core/transaction" + "cosmossdk.io/schema/appdata" "cosmossdk.io/server/v2/stf/branch" "cosmossdk.io/server/v2/stf/gas" "cosmossdk.io/server/v2/stf/mock" ) +const senderAddr = "sender" + func addMsgHandlerToSTF[T any, PT interface { *T transaction.Msg @@ -50,7 +54,7 @@ func addMsgHandlerToSTF[T any, PT interface { t.Errorf("Failed to register handler: %v", err) } - msgRouter, err := msgRouterBuilder.Build() + msgRouter, err := msgRouterBuilder.build() if err != nil { t.Errorf("Failed to build message router: %v", err) } @@ -60,7 +64,7 @@ func addMsgHandlerToSTF[T any, PT interface { func TestSTF(t *testing.T) { state := mock.DB() mockTx := mock.Tx{ - Sender: []byte("sender"), + Sender: []byte(senderAddr), Msg: &gogotypes.BoolValue{Value: true}, GasLimit: 100_000, } @@ -68,22 +72,48 @@ func TestSTF(t *testing.T) { sum := sha256.Sum256([]byte("test-hash")) s := &STF[mock.Tx]{ - doPreBlock: func(ctx context.Context, txs []mock.Tx) error { return nil }, + doPreBlock: func(ctx context.Context, txs []mock.Tx) error { + ctx.(*executionContext).events = append(ctx.(*executionContext).events, event.NewEvent("pre-block")) + return nil + }, doBeginBlock: func(ctx context.Context) error { kvSet(t, ctx, "begin-block") + ctx.(*executionContext).events = append(ctx.(*executionContext).events, event.NewEvent("begin-block")) return nil }, doEndBlock: func(ctx context.Context) error { kvSet(t, ctx, "end-block") + ctx.(*executionContext).events = append(ctx.(*executionContext).events, event.NewEvent("end-block")) return nil }, - doValidatorUpdate: func(ctx context.Context) ([]appmodulev2.ValidatorUpdate, error) { return nil, nil }, + doValidatorUpdate: func(ctx context.Context) ([]appmodulev2.ValidatorUpdate, error) { + ctx.(*executionContext).events = append(ctx.(*executionContext).events, event.NewEvent("validator-update")) + return nil, nil + }, doTxValidation: func(ctx context.Context, tx mock.Tx) error { kvSet(t, ctx, "validate") + ctx.(*executionContext).events = append( + ctx.(*executionContext).events, + event.NewEvent("validate-tx", event.NewAttribute(senderAddr, string(tx.Sender))), + event.NewEvent( + "validate-tx", + event.NewAttribute(senderAddr, string(tx.Sender)), + event.NewAttribute("index", "2"), + ), + ) return nil }, postTxExec: func(ctx context.Context, tx mock.Tx, success bool) error { kvSet(t, ctx, "post-tx-exec") + ctx.(*executionContext).events = append( + ctx.(*executionContext).events, + event.NewEvent("post-tx-exec", event.NewAttribute(senderAddr, string(tx.Sender))), + event.NewEvent( + "post-tx-exec", + event.NewAttribute(senderAddr, string(tx.Sender)), + event.NewAttribute("index", "2"), + ), + ) return nil }, branchFn: branch.DefaultNewWriterMap, @@ -93,6 +123,15 @@ func TestSTF(t *testing.T) { addMsgHandlerToSTF(t, s, func(ctx context.Context, msg *gogotypes.BoolValue) (*gogotypes.BoolValue, error) { kvSet(t, ctx, "exec") + ctx.(*executionContext).events = append( + ctx.(*executionContext).events, + event.NewEvent("handle-msg", event.NewAttribute("msg", msg.String())), + event.NewEvent( + "handle-msg", + event.NewAttribute("msg", msg.String()), + event.NewAttribute("index", "2"), + ), + ) return nil, nil }) @@ -135,13 +174,124 @@ func TestSTF(t *testing.T) { if txResult.GasWanted != mockTx.GasLimit { t.Errorf("Expected GasWanted to be %d, got %d", mockTx.GasLimit, txResult.GasWanted) } + + // Check PreBlockEvents + preBlockEvents := result.PreBlockEvents + if len(preBlockEvents) != 1 { + t.Fatalf("Expected 1 PreBlockEvent, got %d", len(preBlockEvents)) + } + if preBlockEvents[0].Type != "pre-block" { + t.Errorf("Expected PreBlockEvent Type 'pre-block', got %s", preBlockEvents[0].Type) + } + if preBlockEvents[0].BlockStage != appdata.PreBlockStage { + t.Errorf("Expected PreBlockStage %d, got %d", appdata.PreBlockStage, preBlockEvents[0].BlockStage) + } + if preBlockEvents[0].EventIndex != 1 { + t.Errorf("Expected PreBlockEventIndex 1, got %d", preBlockEvents[0].EventIndex) + } + // Check BeginBlockEvents + beginBlockEvents := result.BeginBlockEvents + if len(beginBlockEvents) != 1 { + t.Fatalf("Expected 1 BeginBlockEvent, got %d", len(beginBlockEvents)) + } + if beginBlockEvents[0].Type != "begin-block" { + t.Errorf("Expected BeginBlockEvent Type 'begin-block', got %s", beginBlockEvents[0].Type) + } + if beginBlockEvents[0].BlockStage != appdata.BeginBlockStage { + t.Errorf("Expected BeginBlockStage %d, got %d", appdata.BeginBlockStage, beginBlockEvents[0].BlockStage) + } + if beginBlockEvents[0].EventIndex != 1 { + t.Errorf("Expected BeginBlockEventIndex 1, got %d", beginBlockEvents[0].EventIndex) + } + // Check EndBlockEvents + endBlockEvents := result.EndBlockEvents + if len(endBlockEvents) != 2 { + t.Fatalf("Expected 2 EndBlockEvents, got %d", len(endBlockEvents)) + } + if endBlockEvents[0].Type != "end-block" { + t.Errorf("Expected EndBlockEvent Type 'end-block', got %s", endBlockEvents[0].Type) + } + if endBlockEvents[1].Type != "validator-update" { + t.Errorf("Expected EndBlockEvent Type 'validator-update', got %s", endBlockEvents[1].Type) + } + if endBlockEvents[1].BlockStage != appdata.EndBlockStage { + t.Errorf("Expected EndBlockStage %d, got %d", appdata.EndBlockStage, endBlockEvents[1].BlockStage) + } + if endBlockEvents[0].EventIndex != 1 { + t.Errorf("Expected EndBlockEventIndex 1, got %d", endBlockEvents[0].EventIndex) + } + if endBlockEvents[1].EventIndex != 2 { + t.Errorf("Expected EndBlockEventIndex 2, got %d", endBlockEvents[1].EventIndex) + } + // check TxEvents + events := txResult.Events + if len(events) != 6 { + t.Fatalf("Expected 6 TxEvents, got %d", len(events)) + } + for i, event := range events { + if event.BlockStage != appdata.TxProcessingStage { + t.Errorf("Expected BlockStage %d, got %d", appdata.TxProcessingStage, event.BlockStage) + } + if event.TxIndex != 1 { + t.Errorf("Expected TxIndex 1, got %d", event.TxIndex) + } + if event.EventIndex != int32(i%2+1) { + t.Errorf("Expected EventIndex %d, got %d", i%2+1, event.EventIndex) + } + + attrs, err := event.Attributes() + if err != nil { + t.Fatalf("Error getting event attributes: %v", err) + } + if len(attrs) < 1 || len(attrs) > 2 { + t.Errorf("Expected 1 or 2 attributes, got %d", len(attrs)) + } + + if len(attrs) == 2 { + if attrs[1].Key != "index" || attrs[1].Value != "2" { + t.Errorf("Expected attribute key 'index' and value '2', got key '%s' and value '%s'", attrs[1].Key, attrs[1].Value) + } + } + switch i { + case 0, 1: + if event.Type != "validate-tx" { + t.Errorf("Expected event type 'validate-tx', got %s", event.Type) + } + if event.MsgIndex != 0 { + t.Errorf("Expected MsgIndex 0, got %d", event.MsgIndex) + } + if attrs[0].Key != senderAddr || attrs[0].Value != senderAddr { + t.Errorf("Expected sender attribute key 'sender' and value 'sender', got key '%s' and value '%s'", attrs[0].Key, attrs[0].Value) + } + case 2, 3: + if event.Type != "handle-msg" { + t.Errorf("Expected event type 'handle-msg', got %s", event.Type) + } + if event.MsgIndex != 1 { + t.Errorf("Expected MsgIndex 1, got %d", event.MsgIndex) + } + if attrs[0].Key != "msg" || attrs[0].Value != "&BoolValue{Value:true,XXX_unrecognized:[],}" { + t.Errorf("Expected msg attribute with value '&BoolValue{Value:true,XXX_unrecognized:[],}', got '%s'", attrs[0].Value) + } + case 4, 5: + if event.Type != "post-tx-exec" { + t.Errorf("Expected event type 'post-tx-exec', got %s", event.Type) + } + if event.MsgIndex != -1 { + t.Errorf("Expected MsgIndex -1, got %d", event.MsgIndex) + } + if attrs[0].Key != senderAddr || attrs[0].Value != senderAddr { + t.Errorf("Expected sender attribute key 'sender' and value 'sender', got key '%s' and value '%s'", attrs[0].Key, attrs[0].Value) + } + } + } }) t.Run("exec tx out of gas", func(t *testing.T) { s := s.clone() mockTx := mock.Tx{ - Sender: []byte("sender"), + Sender: []byte(senderAddr), Msg: &gogotypes.BoolValue{Value: true}, // msg does not matter at all because our handler does nothing. GasLimit: 0, // NO GAS! } diff --git a/server/v2/store/commands.go b/server/v2/store/commands.go index 7c50995f923e..3b9f175c7b0f 100644 --- a/server/v2/store/commands.go +++ b/server/v2/store/commands.go @@ -16,8 +16,8 @@ import ( "cosmossdk.io/store/v2/root" ) -// QueryBlockResultsCmd implements the default command for a BlockResults query. -func (s *StoreComponent[T]) PrunesCmd() *cobra.Command { +// PrunesCmd implements the default command for pruning app history states. +func (s *Server[T]) PrunesCmd() *cobra.Command { cmd := &cobra.Command{ Use: "prune [pruning-method]", Short: "Prune app history states by keeping the recent heights and deleting old heights", diff --git a/server/v2/store/server.go b/server/v2/store/server.go index a5f464c964a5..c50a53dc6e24 100644 --- a/server/v2/store/server.go +++ b/server/v2/store/server.go @@ -12,49 +12,49 @@ import ( ) var ( - _ serverv2.ServerComponent[transaction.Tx] = (*StoreComponent[transaction.Tx])(nil) - _ serverv2.HasConfig = (*StoreComponent[transaction.Tx])(nil) - _ serverv2.HasCLICommands = (*StoreComponent[transaction.Tx])(nil) + _ serverv2.ServerComponent[transaction.Tx] = (*Server[transaction.Tx])(nil) + _ serverv2.HasConfig = (*Server[transaction.Tx])(nil) + _ serverv2.HasCLICommands = (*Server[transaction.Tx])(nil) ) const ServerName = "store" -// StoreComponent manages store config -// and contains prune & snapshot commands -type StoreComponent[T transaction.Tx] struct { +// Server manages store config and contains prune & snapshot commands +type Server[T transaction.Tx] struct { config *Config // saving appCreator for only RestoreSnapshotCmd appCreator serverv2.AppCreator[T] } -func New[T transaction.Tx](appCreator serverv2.AppCreator[T]) *StoreComponent[T] { - return &StoreComponent[T]{appCreator: appCreator} +func New[T transaction.Tx](appCreator serverv2.AppCreator[T]) *Server[T] { + return &Server[T]{appCreator: appCreator} } -func (s *StoreComponent[T]) Init(appI serverv2.AppI[T], cfg map[string]any, logger log.Logger) error { - serverCfg := DefaultConfig() +func (s *Server[T]) Init(appI serverv2.AppI[T], cfg map[string]any, logger log.Logger) error { + serverCfg := s.Config().(*Config) if len(cfg) > 0 { if err := serverv2.UnmarshalSubConfig(cfg, s.Name(), &serverCfg); err != nil { return fmt.Errorf("failed to unmarshal config: %w", err) } } + s.config = serverCfg return nil } -func (s *StoreComponent[T]) Name() string { +func (s *Server[T]) Name() string { return ServerName } -func (s *StoreComponent[T]) Start(ctx context.Context) error { +func (s *Server[T]) Start(ctx context.Context) error { return nil } -func (s *StoreComponent[T]) Stop(ctx context.Context) error { +func (s *Server[T]) Stop(ctx context.Context) error { return nil } -func (s *StoreComponent[T]) CLICommands() serverv2.CLIConfig { +func (s *Server[T]) CLICommands() serverv2.CLIConfig { return serverv2.CLIConfig{ Commands: []*cobra.Command{ s.PrunesCmd(), @@ -68,10 +68,10 @@ func (s *StoreComponent[T]) CLICommands() serverv2.CLIConfig { } } -func (g *StoreComponent[T]) Config() any { - if g.config == nil || g.config == (&Config{}) { +func (s *Server[T]) Config() any { + if s.config == nil || s.config.AppDBBackend == "" { return DefaultConfig() } - return g.config + return s.config } diff --git a/server/v2/store/snapshot.go b/server/v2/store/snapshot.go index 2c106f85fe69..b804e34b71c8 100644 --- a/server/v2/store/snapshot.go +++ b/server/v2/store/snapshot.go @@ -24,8 +24,8 @@ import ( const SnapshotFileName = "_snapshot" -// QueryBlockResultsCmd implements the default command for a BlockResults query. -func (s *StoreComponent[T]) ExportSnapshotCmd() *cobra.Command { +// ExportSnapshotCmd exports app state to snapshot store. +func (s *Server[T]) ExportSnapshotCmd() *cobra.Command { cmd := &cobra.Command{ Use: "export", Short: "Export app state to snapshot store", @@ -76,7 +76,7 @@ func (s *StoreComponent[T]) ExportSnapshotCmd() *cobra.Command { } // RestoreSnapshotCmd returns a command to restore a snapshot -func (s *StoreComponent[T]) RestoreSnapshotCmd(newApp serverv2.AppCreator[T]) *cobra.Command { +func (s *Server[T]) RestoreSnapshotCmd(newApp serverv2.AppCreator[T]) *cobra.Command { cmd := &cobra.Command{ Use: "restore ", Short: "Restore app state from local snapshot", @@ -113,7 +113,7 @@ func (s *StoreComponent[T]) RestoreSnapshotCmd(newApp serverv2.AppCreator[T]) *c } // ListSnapshotsCmd returns the command to list local snapshots -func (s *StoreComponent[T]) ListSnapshotsCmd() *cobra.Command { +func (s *Server[T]) ListSnapshotsCmd() *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "List local snapshots", @@ -139,7 +139,7 @@ func (s *StoreComponent[T]) ListSnapshotsCmd() *cobra.Command { } // DeleteSnapshotCmd returns the command to delete a local snapshot -func (s *StoreComponent[T]) DeleteSnapshotCmd() *cobra.Command { +func (s *Server[T]) DeleteSnapshotCmd() *cobra.Command { return &cobra.Command{ Use: "delete ", Short: "Delete a local snapshot", @@ -167,7 +167,7 @@ func (s *StoreComponent[T]) DeleteSnapshotCmd() *cobra.Command { } // DumpArchiveCmd returns a command to dump the snapshot as portable archive format -func (s *StoreComponent[T]) DumpArchiveCmd() *cobra.Command { +func (s *Server[T]) DumpArchiveCmd() *cobra.Command { cmd := &cobra.Command{ Use: "dump ", Short: "Dump the snapshot as portable archive format", @@ -260,7 +260,7 @@ func (s *StoreComponent[T]) DumpArchiveCmd() *cobra.Command { } // LoadArchiveCmd load a portable archive format snapshot into snapshot store -func (s *StoreComponent[T]) LoadArchiveCmd() *cobra.Command { +func (s *Server[T]) LoadArchiveCmd() *cobra.Command { return &cobra.Command{ Use: "load ", Short: "Load a snapshot archive file (.tar.gz) into snapshot store", diff --git a/server/v2/streaming/plugin.md b/server/v2/streaming/plugin.md index 9eedff9ea2ac..7a1d15bd4307 100644 --- a/server/v2/streaming/plugin.md +++ b/server/v2/streaming/plugin.md @@ -29,7 +29,7 @@ To generate the stubs the local client implementation can call, run the followin make proto-gen ``` -For other languages you'll need to [download](https://github.com/cosmos/cosmos-sdk/blob/main/third_party/proto/README.md) +For other languages you'll need to [download](https://github.com/cosmos/cosmos-sdk/blob/main/proto/README.md#generate) the CosmosSDK protos into your project and compile. For language specific compilation instructions visit [https://github.com/grpc](https://github.com/grpc) and look in the `examples` folder of your language of choice `https://github.com/grpc/grpc-{language}/tree/master/examples` and [https://grpc.io](https://grpc.io) diff --git a/server/v2/streaming/utils.go b/server/v2/streaming/utils.go index 658f2e978d4b..0266d5526b3c 100644 --- a/server/v2/streaming/utils.go +++ b/server/v2/streaming/utils.go @@ -2,15 +2,18 @@ package streaming import "cosmossdk.io/core/event" -func IntoStreamingEvents(events []event.Event) []*Event { +func IntoStreamingEvents(events []event.Event) ([]*Event, error) { streamingEvents := make([]*Event, len(events)) for _, event := range events { strEvent := &Event{ Type: event.Type, } - - for _, eventValue := range event.Attributes { + attrs, err := event.Attributes() + if err != nil { + return nil, err + } + for _, eventValue := range attrs { strEvent.Attributes = append(strEvent.Attributes, &EventAttribute{ Key: eventValue.Key, Value: eventValue.Value, @@ -19,5 +22,5 @@ func IntoStreamingEvents(events []event.Event) []*Event { streamingEvents = append(streamingEvents, strEvent) } - return streamingEvents + return streamingEvents, nil } diff --git a/server/v2/types.go b/server/v2/types.go index f25dbb8ab388..7cd15fd10307 100644 --- a/server/v2/types.go +++ b/server/v2/types.go @@ -1,9 +1,9 @@ package serverv2 import ( - gogoproto "github.com/cosmos/gogoproto/proto" "github.com/spf13/viper" + appmodulev2 "cosmossdk.io/core/appmodule/v2" "cosmossdk.io/core/server" "cosmossdk.io/core/transaction" "cosmossdk.io/log" @@ -16,7 +16,6 @@ type AppI[T transaction.Tx] interface { Name() string InterfaceRegistry() server.InterfaceRegistry GetAppManager() *appmanager.AppManager[T] - GetConsensusAuthority() string // TODO remove - GetGPRCMethodsToMessageMap() map[string]func() gogoproto.Message + GetQueryHandlers() map[string]appmodulev2.Handler GetStore() any } diff --git a/simapp/app.go b/simapp/app.go index 00f27cacb87e..96ae2f04dbae 100644 --- a/simapp/app.go +++ b/simapp/app.go @@ -11,6 +11,8 @@ import ( "path/filepath" abci "github.com/cometbft/cometbft/api/cometbft/abci/v1" + cmtcrypto "github.com/cometbft/cometbft/crypto" + cmted25519 "github.com/cometbft/cometbft/crypto/ed25519" "github.com/cosmos/gogoproto/proto" "github.com/spf13/cast" @@ -26,6 +28,7 @@ import ( "cosmossdk.io/x/accounts/accountstd" baseaccount "cosmossdk.io/x/accounts/defaults/base" lockup "cosmossdk.io/x/accounts/defaults/lockup" + "cosmossdk.io/x/accounts/defaults/multisig" "cosmossdk.io/x/accounts/testing/account_abstraction" "cosmossdk.io/x/accounts/testing/counter" "cosmossdk.io/x/authz" @@ -163,7 +166,7 @@ type SimApp struct { BankKeeper bankkeeper.BaseKeeper StakingKeeper *stakingkeeper.Keeper SlashingKeeper slashingkeeper.Keeper - MintKeeper mintkeeper.Keeper + MintKeeper *mintkeeper.Keeper DistrKeeper distrkeeper.Keeper GovKeeper govkeeper.Keeper UpgradeKeeper *upgradekeeper.Keeper @@ -183,7 +186,7 @@ type SimApp struct { sm *module.SimulationManager // module configurator - configurator module.Configurator // nolint:staticcheck // SA1019: Configurator is deprecated but still used in runtime v1. + configurator module.Configurator //nolint:staticcheck // SA1019: Configurator is deprecated but still used in runtime v1. } func init() { @@ -313,6 +316,7 @@ func NewSimApp( accountstd.AddAccount(lockup.PERIODIC_LOCKING_ACCOUNT, lockup.NewPeriodicLockingAccount), accountstd.AddAccount(lockup.DELAYED_LOCKING_ACCOUNT, lockup.NewDelayedLockingAccount), accountstd.AddAccount(lockup.PERMANENT_LOCKING_ACCOUNT, lockup.NewPermanentLockingAccount), + accountstd.AddAccount("multisig", multisig.NewAccount), // PRODUCTION: add baseaccount.NewAccount("base", txConfig.SignModeHandler(), baseaccount.WithSecp256K1PubKey()), ) @@ -370,7 +374,10 @@ func NewSimApp( cometService, ) - app.MintKeeper = mintkeeper.NewKeeper(appCodec, runtime.NewEnvironment(runtime.NewKVStoreService(keys[minttypes.StoreKey]), logger.With(log.ModuleKey, "x/mint")), app.StakingKeeper, app.AuthKeeper, app.BankKeeper, authtypes.FeeCollectorName, govModuleAddr) + app.MintKeeper = mintkeeper.NewKeeper(appCodec, runtime.NewEnvironment(runtime.NewKVStoreService(keys[minttypes.StoreKey]), logger.With(log.ModuleKey, "x/mint")), app.AuthKeeper, app.BankKeeper, authtypes.FeeCollectorName, govModuleAddr) + if err := app.MintKeeper.SetMintFn(mintkeeper.DefaultMintFn(minttypes.DefaultInflationCalculationFn, app.StakingKeeper, app.MintKeeper)); err != nil { + panic(err) + } app.PoolKeeper = poolkeeper.NewKeeper(appCodec, runtime.NewEnvironment(runtime.NewKVStoreService(keys[pooltypes.StoreKey]), logger.With(log.ModuleKey, "x/protocolpool")), app.AuthKeeper, app.BankKeeper, app.StakingKeeper, govModuleAddr) @@ -391,7 +398,7 @@ func NewSimApp( app.CircuitKeeper = circuitkeeper.NewKeeper(runtime.NewEnvironment(runtime.NewKVStoreService(keys[circuittypes.StoreKey]), logger.With(log.ModuleKey, "x/circuit")), appCodec, govModuleAddr, app.AuthKeeper.AddressCodec()) app.BaseApp.SetCircuitBreaker(&app.CircuitKeeper) - app.AuthzKeeper = authzkeeper.NewKeeper(runtime.NewEnvironment(runtime.NewKVStoreService(keys[authzkeeper.StoreKey]), logger.With(log.ModuleKey, "x/authz"), runtime.EnvWithMsgRouterService(app.MsgServiceRouter()), runtime.EnvWithQueryRouterService(app.GRPCQueryRouter())), appCodec, app.AuthKeeper) + app.AuthzKeeper = authzkeeper.NewKeeper(runtime.NewEnvironment(runtime.NewKVStoreService(keys[authzkeeper.StoreKey]), logger.With(log.ModuleKey, "x/authz"), runtime.EnvWithMsgRouterService(app.MsgServiceRouter()), runtime.EnvWithQueryRouterService(app.GRPCQueryRouter())), appCodec, signingCtx.AddressCodec()) groupConfig := group.DefaultConfig() /* @@ -437,7 +444,13 @@ func NewSimApp( // create evidence keeper with router evidenceKeeper := evidencekeeper.NewKeeper( - appCodec, runtime.NewEnvironment(runtime.NewKVStoreService(keys[evidencetypes.StoreKey]), logger.With(log.ModuleKey, "x/evidence"), runtime.EnvWithMsgRouterService(app.MsgServiceRouter()), runtime.EnvWithQueryRouterService(app.GRPCQueryRouter())), app.StakingKeeper, app.SlashingKeeper, app.ConsensusParamsKeeper, app.AuthKeeper.AddressCodec(), + appCodec, + runtime.NewEnvironment(runtime.NewKVStoreService(keys[evidencetypes.StoreKey]), logger.With(log.ModuleKey, "x/evidence"), runtime.EnvWithMsgRouterService(app.MsgServiceRouter()), runtime.EnvWithQueryRouterService(app.GRPCQueryRouter())), + app.StakingKeeper, + app.SlashingKeeper, + app.ConsensusParamsKeeper, + app.AuthKeeper.AddressCodec(), + app.StakingKeeper.ConsensusAddressCodec(), ) // If evidence needs to be handled for the app, set routes in router here and seal app.EvidenceKeeper = *evidenceKeeper @@ -463,15 +476,15 @@ func NewSimApp( auth.NewAppModule(appCodec, app.AuthKeeper, app.AccountsKeeper, authsims.RandomGenesisAccounts, nil), vesting.NewAppModule(app.AuthKeeper, app.BankKeeper), bank.NewAppModule(appCodec, app.BankKeeper, app.AuthKeeper), - feegrantmodule.NewAppModule(appCodec, app.AuthKeeper, app.BankKeeper, app.FeeGrantKeeper, app.interfaceRegistry), + feegrantmodule.NewAppModule(appCodec, app.FeeGrantKeeper, app.interfaceRegistry), gov.NewAppModule(appCodec, &app.GovKeeper, app.AuthKeeper, app.BankKeeper, app.PoolKeeper), - mint.NewAppModule(appCodec, app.MintKeeper, app.AuthKeeper, nil), + mint.NewAppModule(appCodec, app.MintKeeper, app.AuthKeeper), slashing.NewAppModule(appCodec, app.SlashingKeeper, app.AuthKeeper, app.BankKeeper, app.StakingKeeper, app.interfaceRegistry, cometService), - distr.NewAppModule(appCodec, app.DistrKeeper, app.AuthKeeper, app.BankKeeper, app.StakingKeeper), - staking.NewAppModule(appCodec, app.StakingKeeper, app.AuthKeeper, app.BankKeeper), + distr.NewAppModule(appCodec, app.DistrKeeper, app.StakingKeeper), + staking.NewAppModule(appCodec, app.StakingKeeper), upgrade.NewAppModule(app.UpgradeKeeper), evidence.NewAppModule(appCodec, app.EvidenceKeeper, cometService), - authzmodule.NewAppModule(appCodec, app.AuthzKeeper, app.AuthKeeper, app.BankKeeper, app.interfaceRegistry), + authzmodule.NewAppModule(appCodec, app.AuthzKeeper, app.interfaceRegistry), groupmodule.NewAppModule(appCodec, app.GroupKeeper, app.AuthKeeper, app.BankKeeper, app.interfaceRegistry), nftmodule.NewAppModule(appCodec, app.NFTKeeper, app.AuthKeeper, app.BankKeeper, app.interfaceRegistry), consensus.NewAppModule(appCodec, app.ConsensusParamsKeeper), @@ -705,7 +718,7 @@ func (app *SimApp) EndBlocker(ctx sdk.Context) (sdk.EndBlock, error) { return app.ModuleManager.EndBlock(ctx) } -func (a *SimApp) Configurator() module.Configurator { // nolint:staticcheck // SA1019: Configurator is deprecated but still used in runtime v1. +func (a *SimApp) Configurator() module.Configurator { //nolint:staticcheck // SA1019: Configurator is deprecated but still used in runtime v1. return a.configurator } @@ -831,6 +844,14 @@ func (app *SimApp) RegisterNodeService(clientCtx client.Context, cfg config.Conf nodeservice.RegisterNodeService(clientCtx, app.GRPCQueryRouter(), cfg) } +// ValidatorKeyProvider returns a function that generates a validator key +// Supported key types are those supported by Comet: ed25519, secp256k1, bls12-381 +func (app *SimApp) ValidatorKeyProvider() runtime.KeyGenF { + return func() (cmtcrypto.PrivKey, error) { + return cmted25519.GenPrivKey(), nil + } +} + // GetMaccPerms returns a copy of the module account permissions // // NOTE: This is solely to be used for testing purposes. diff --git a/simapp/app_config.go b/simapp/app_config.go index ca1971950628..33e11841e795 100644 --- a/simapp/app_config.go +++ b/simapp/app_config.go @@ -28,6 +28,7 @@ import ( stakingmodulev1 "cosmossdk.io/api/cosmos/staking/module/v1" txconfigv1 "cosmossdk.io/api/cosmos/tx/config/v1" upgrademodulev1 "cosmossdk.io/api/cosmos/upgrade/module/v1" + validatemodulev1 "cosmossdk.io/api/cosmos/validate/module/v1" vestingmodulev1 "cosmossdk.io/api/cosmos/vesting/module/v1" "cosmossdk.io/depinject/appconfig" "cosmossdk.io/x/accounts" @@ -69,11 +70,12 @@ import ( "github.com/cosmos/cosmos-sdk/runtime" _ "github.com/cosmos/cosmos-sdk/testutil/x/counter" // import for side-effects - _ "github.com/cosmos/cosmos-sdk/x/auth/tx/config" // import for side-effects + authtxconfig "github.com/cosmos/cosmos-sdk/x/auth/tx/config" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" _ "github.com/cosmos/cosmos-sdk/x/auth/vesting" // import for side-effects vestingtypes "github.com/cosmos/cosmos-sdk/x/auth/vesting/types" genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types" + "github.com/cosmos/cosmos-sdk/x/validate" ) var ( @@ -181,10 +183,19 @@ var ( // SkipStoreKeys is an optional list of store keys to skip when constructing the // module's keeper. This is useful when a module does not have a store key. SkipStoreKeys: []string{ - "tx", + authtxconfig.DepinjectModuleName, + validate.ModuleName, }, }), }, + { + Name: authtxconfig.DepinjectModuleName, // x/auth/tx/config depinject module (not app module), use to provide tx configuration + Config: appconfig.WrapAny(&txconfigv1.Config{}), + }, + { + Name: validate.ModuleName, + Config: appconfig.WrapAny(&validatemodulev1.Module{}), + }, { Name: authtypes.ModuleName, Config: appconfig.WrapAny(&authmodulev1.Module{ @@ -218,12 +229,6 @@ var ( Name: slashingtypes.ModuleName, Config: appconfig.WrapAny(&slashingmodulev1.Module{}), }, - { - Name: "tx", - Config: appconfig.WrapAny(&txconfigv1.Config{ - SkipAnteHandler: true, // SimApp is using non default AnteHandler such as circuit and unorderedtx decorators - }), - }, { Name: genutiltypes.ModuleName, Config: appconfig.WrapAny(&genutilmodulev1.Module{}), diff --git a/simapp/app_di.go b/simapp/app_di.go index 32046a59b7e0..b26220892e0d 100644 --- a/simapp/app_di.go +++ b/simapp/app_di.go @@ -15,6 +15,9 @@ import ( "cosmossdk.io/depinject" "cosmossdk.io/log" "cosmossdk.io/x/accounts" + basedepinject "cosmossdk.io/x/accounts/defaults/base/depinject" + lockupdepinject "cosmossdk.io/x/accounts/defaults/lockup/depinject" + multisigdepinject "cosmossdk.io/x/accounts/defaults/multisig/depinject" bankkeeper "cosmossdk.io/x/bank/keeper" circuitkeeper "cosmossdk.io/x/circuit/keeper" consensuskeeper "cosmossdk.io/x/consensus/keeper" @@ -155,6 +158,27 @@ func NewSimApp( // For providing a custom inflation function for x/mint add here your // custom function that implements the minttypes.MintFn interface. ), + depinject.Provide( + // inject desired account types: + multisigdepinject.ProvideAccount, + basedepinject.ProvideAccount, + lockupdepinject.ProvideAllLockupAccounts, + + // provide base account options + basedepinject.ProvideSecp256K1PubKey, + // if you want to provide a custom public key you + // can do it from here. + // Example: + // basedepinject.ProvideCustomPubkey[Ed25519PublicKey]() + // + // You can also provide a custom public key with a custom validation function: + // + // basedepinject.ProvideCustomPubKeyAndValidationFunc(func(pub Ed25519PublicKey) error { + // if len(pub.Key) != 64 { + // return fmt.Errorf("invalid pub key size") + // } + // }) + ), ) ) diff --git a/simapp/genesis_account_test.go b/simapp/genesis_account_test.go index d813e9ec7e31..eccb8cc66c6e 100644 --- a/simapp/genesis_account_test.go +++ b/simapp/genesis_account_test.go @@ -81,7 +81,6 @@ func TestSimGenesisAccountValidate(t *testing.T) { } for _, tc := range testCases { - tc := tc t.Run(tc.name, func(t *testing.T) { require.Equal(t, tc.wantErr, tc.sga.Validate() != nil) }) diff --git a/simapp/go.mod b/simapp/go.mod index 526905f0f11e..c2eeafc74d92 100644 --- a/simapp/go.mod +++ b/simapp/go.mod @@ -3,17 +3,17 @@ module cosmossdk.io/simapp go 1.23.1 require ( - cosmossdk.io/api v0.7.5 + cosmossdk.io/api v0.7.6 cosmossdk.io/client/v2 v2.0.0-20230630094428-02b760776860 cosmossdk.io/collections v0.4.0 - cosmossdk.io/core v1.0.0-alpha.2 - cosmossdk.io/core/testing v0.0.0-00010101000000-000000000000 + cosmossdk.io/core v1.0.0-alpha.4 + cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29 cosmossdk.io/depinject v1.0.0 cosmossdk.io/log v1.4.1 cosmossdk.io/math v1.3.0 - cosmossdk.io/store v1.1.1-0.20240418092142-896cdf1971bc + cosmossdk.io/store v1.1.1 cosmossdk.io/tools/confix v0.0.0-20230613133644-0a778132a60f - cosmossdk.io/x/accounts v0.0.0-20240226161501-23359a0b6d91 + cosmossdk.io/x/accounts v0.0.0-20240913065641-0064ccbce64e cosmossdk.io/x/accounts/defaults/lockup v0.0.0-20240417181816-5e7aae0db1f5 cosmossdk.io/x/authz v0.0.0-00010101000000-000000000000 cosmossdk.io/x/bank v0.0.0-20240226161501-23359a0b6d91 @@ -30,11 +30,10 @@ require ( cosmossdk.io/x/protocolpool v0.0.0-20230925135524-a1bc045b3190 cosmossdk.io/x/slashing v0.0.0-00010101000000-000000000000 cosmossdk.io/x/staking v0.0.0-20240226161501-23359a0b6d91 - cosmossdk.io/x/tx v0.13.4 + cosmossdk.io/x/tx v0.13.5 cosmossdk.io/x/upgrade v0.0.0-20230613133644-0a778132a60f github.com/cometbft/cometbft v1.0.0-rc1.0.20240908111210-ab0be101882f github.com/cometbft/cometbft/api v1.0.0-rc.1 - github.com/cosmos/cosmos-db v1.0.3-0.20240911104526-ddc3f09bfc22 // indirect // this version is not used as it is always replaced by the latest Cosmos SDK version github.com/cosmos/cosmos-sdk v0.53.0 github.com/cosmos/gogoproto v1.7.0 @@ -47,7 +46,11 @@ require ( google.golang.org/protobuf v1.34.2 ) -require google.golang.org/grpc v1.66.2 +require ( + cosmossdk.io/x/accounts/defaults/base v0.0.0-00010101000000-000000000000 + cosmossdk.io/x/accounts/defaults/multisig v0.0.0-00010101000000-000000000000 + google.golang.org/grpc v1.67.1 +) require ( buf.build/gen/go/cometbft/cometbft/protocolbuffers/go v1.34.2-20240701160653-fedbb9acfd2f.2 // indirect @@ -59,8 +62,7 @@ require ( cloud.google.com/go/iam v1.1.13 // indirect cloud.google.com/go/storage v1.43.0 // indirect cosmossdk.io/errors v1.0.1 // indirect - cosmossdk.io/schema v0.2.0 // indirect - cosmossdk.io/x/accounts/defaults/multisig v0.0.0-00010101000000-000000000000 // indirect + cosmossdk.io/schema v0.3.1-0.20240930054013-7c6e0388a3f9 // indirect filippo.io/edwards25519 v1.1.0 // indirect github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect github.com/99designs/keyring v1.2.2 // indirect @@ -85,6 +87,7 @@ require ( github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect github.com/cometbft/cometbft-db v0.15.0 // indirect github.com/cosmos/btcutil v1.0.5 // indirect + github.com/cosmos/cosmos-db v1.0.3-0.20240911104526-ddc3f09bfc22 // indirect github.com/cosmos/cosmos-proto v1.0.0-beta.5 // indirect github.com/cosmos/crypto v0.1.2 // indirect github.com/cosmos/go-bip39 v1.0.0 // indirect @@ -144,7 +147,7 @@ require ( github.com/hashicorp/hcl v1.0.0 // indirect github.com/hashicorp/yamux v0.1.1 // indirect github.com/hdevalence/ed25519consensus v0.2.0 // indirect - github.com/huandu/skiplist v1.2.0 // indirect + github.com/huandu/skiplist v1.2.1 // indirect github.com/iancoleman/strcase v0.3.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect @@ -174,14 +177,14 @@ require ( github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/client_golang v1.20.3 // indirect + github.com/prometheus/client_golang v1.20.4 // indirect github.com/prometheus/client_model v0.6.1 // indirect - github.com/prometheus/common v0.59.1 // indirect + github.com/prometheus/common v0.60.0 // indirect github.com/prometheus/procfs v0.15.1 // indirect github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect github.com/rivo/uniseg v0.2.0 // indirect github.com/rogpeppe/go-internal v1.12.0 // indirect - github.com/rs/cors v1.11.0 // indirect + github.com/rs/cors v1.11.1 // indirect github.com/rs/zerolog v1.33.0 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect @@ -210,7 +213,7 @@ require ( golang.org/x/exp v0.0.0-20240531132922-fd00a4e0eefc // indirect golang.org/x/mod v0.17.0 // indirect golang.org/x/net v0.29.0 // indirect - golang.org/x/oauth2 v0.22.0 // indirect + golang.org/x/oauth2 v0.23.0 // indirect golang.org/x/sync v0.8.0 // indirect golang.org/x/sys v0.25.0 // indirect golang.org/x/term v0.24.0 // indirect @@ -220,7 +223,7 @@ require ( google.golang.org/api v0.192.0 // indirect google.golang.org/genproto v0.0.0-20240814211410-ddb44dafa142 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect gotest.tools/v3 v3.5.1 // indirect @@ -240,10 +243,10 @@ replace ( cosmossdk.io/api => ../api cosmossdk.io/client/v2 => ../client/v2 cosmossdk.io/collections => ../collections - cosmossdk.io/core/testing => ../core/testing cosmossdk.io/store => ../store cosmossdk.io/tools/confix => ../tools/confix cosmossdk.io/x/accounts => ../x/accounts + cosmossdk.io/x/accounts/defaults/base => ../x/accounts/defaults/base cosmossdk.io/x/accounts/defaults/lockup => ../x/accounts/defaults/lockup cosmossdk.io/x/accounts/defaults/multisig => ../x/accounts/defaults/multisig cosmossdk.io/x/authz => ../x/authz diff --git a/simapp/go.sum b/simapp/go.sum index f823b8f23e9f..84be5993cd65 100644 --- a/simapp/go.sum +++ b/simapp/go.sum @@ -192,8 +192,10 @@ cloud.google.com/go/webrisk v1.4.0/go.mod h1:Hn8X6Zr+ziE2aNd8SliSDWpEnSS1u4R9+xX cloud.google.com/go/webrisk v1.5.0/go.mod h1:iPG6fr52Tv7sGk0H6qUFzmL3HHZev1htXuWDEEsqMTg= cloud.google.com/go/workflows v1.6.0/go.mod h1:6t9F5h/unJz41YqfBmqSASJSXccBLtD1Vwf+KmJENM0= cloud.google.com/go/workflows v1.7.0/go.mod h1:JhSrZuVZWuiDfKEFxU0/F1PQjmpnpcoISEXH2bcHC3M= -cosmossdk.io/core v1.0.0-alpha.2 h1:epU0Xwces4Rgl5bMhHHkXGaGDcyucNGlC/JDH+Suckg= -cosmossdk.io/core v1.0.0-alpha.2/go.mod h1:abgLjeFLhtuKIYZWSPlVUgQBrKObO7ULV35KYfexE90= +cosmossdk.io/core v1.0.0-alpha.4 h1:9iuroT9ejDYETCsGkzkvs/wAY/5UFl7nCIINFRxyMJY= +cosmossdk.io/core v1.0.0-alpha.4/go.mod h1:3u9cWq1FAVtiiCrDPpo4LhR+9V6k/ycSG4/Y/tREWCY= +cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29 h1:NxxUo0GMJUbIuVg0R70e3cbn9eFTEuMr7ev1AFvypdY= +cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29/go.mod h1:8s2tPeJtSiQuoyPmr2Ag7meikonISO4Fv4MoO8+ORrs= cosmossdk.io/depinject v1.0.0 h1:dQaTu6+O6askNXO06+jyeUAnF2/ssKwrrszP9t5q050= cosmossdk.io/depinject v1.0.0/go.mod h1:zxK/h3HgHoA/eJVtiSsoaRaRA2D5U4cJ5thIG4ssbB8= cosmossdk.io/errors v1.0.1 h1:bzu+Kcr0kS/1DuPBtUFdWjzLqyUuCiyHjyJB6srBV/0= @@ -202,8 +204,8 @@ cosmossdk.io/log v1.4.1 h1:wKdjfDRbDyZRuWa8M+9nuvpVYxrEOwbD/CA8hvhU8QM= cosmossdk.io/log v1.4.1/go.mod h1:k08v0Pyq+gCP6phvdI6RCGhLf/r425UT6Rk/m+o74rU= cosmossdk.io/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE= cosmossdk.io/math v1.3.0/go.mod h1:vnRTxewy+M7BtXBNFybkuhSH4WfedVAAnERHgVFhp3k= -cosmossdk.io/schema v0.2.0 h1:UH5CR1DqUq8yP+5Np8PbvG4YX0zAUsTN2Qk6yThmfMk= -cosmossdk.io/schema v0.2.0/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= +cosmossdk.io/schema v0.3.1-0.20240930054013-7c6e0388a3f9 h1:DmOoS/1PeY6Ih0hAVlJ69kLMUrLV+TCbfICrZtB1vdU= +cosmossdk.io/schema v0.3.1-0.20240930054013-7c6e0388a3f9/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= @@ -590,8 +592,8 @@ github.com/hdevalence/ed25519consensus v0.2.0/go.mod h1:w3BHWjwJbFU29IRHL1Iqkw3s github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/huandu/go-assert v1.1.5 h1:fjemmA7sSfYHJD7CUqs9qTwwfdNAx7/j2/ZlHXzNB3c= github.com/huandu/go-assert v1.1.5/go.mod h1:yOLvuqZwmcHIC5rIzrBhT7D3Q9c3GFnd0JrPVhn/06U= -github.com/huandu/skiplist v1.2.0 h1:gox56QD77HzSC0w+Ws3MH3iie755GBJU1OER3h5VsYw= -github.com/huandu/skiplist v1.2.0/go.mod h1:7v3iFjLcSAzO4fN5B8dvebvo/qsfumiLiDXMrPiHF9w= +github.com/huandu/skiplist v1.2.1 h1:dTi93MgjwErA/8idWTzIw4Y1kZsMWx35fmI2c8Rij7w= +github.com/huandu/skiplist v1.2.1/go.mod h1:7v3iFjLcSAzO4fN5B8dvebvo/qsfumiLiDXMrPiHF9w= github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI= github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= @@ -719,8 +721,8 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= -github.com/prometheus/client_golang v1.20.3 h1:oPksm4K8B+Vt35tUhw6GbSNSgVlVSBH0qELP/7u83l4= -github.com/prometheus/client_golang v1.20.3/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_golang v1.20.4 h1:Tgh3Yr67PaOv/uTqloMsCEdeuFTatm5zIq5+qNN23vI= +github.com/prometheus/client_golang v1.20.4/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -729,8 +731,8 @@ github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= -github.com/prometheus/common v0.59.1 h1:LXb1quJHWm1P6wq/U824uxYi4Sg0oGvNeUm1z5dJoX0= -github.com/prometheus/common v0.59.1/go.mod h1:GpWM7dewqmVYcd7SmRaiWVe9SSqjf0UrwnYnpEZNuT0= +github.com/prometheus/common v0.60.0 h1:+V9PAREWNvJMAuJ1x1BaWl9dewMW4YrHZQbx0sJNllA= +github.com/prometheus/common v0.60.0/go.mod h1:h0LYf1R1deLSKtD4Vdg8gy4RuOvENW2J/h19V5NADQw= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/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= @@ -745,8 +747,8 @@ github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= -github.com/rs/cors v1.11.0 h1:0B9GE/r9Bc2UxRMMtymBkHTenPkHDv0CW4Y98GBY+po= -github.com/rs/cors v1.11.0/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= +github.com/rs/cors v1.11.1 h1:eU3gRzXLRK57F5rKMGMZURNdIG4EoAmX8k94r9wXWHA= +github.com/rs/cors v1.11.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8= github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= @@ -981,8 +983,8 @@ golang.org/x/oauth2 v0.0.0-20220822191816-0ebed06d0094/go.mod h1:h4gKUeWbJ4rQPri golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= golang.org/x/oauth2 v0.1.0/go.mod h1:G9FE4dLTsbXUu90h/Pf85g4w1D+SSAgR+q46nJZ8M4A= -golang.org/x/oauth2 v0.22.0 h1:BzDx2FehcG7jJwgWLELCdmLuxk2i+x9UDpSiss2u0ZA= -golang.org/x/oauth2 v0.22.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/oauth2 v0.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs= +golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= 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= @@ -1336,8 +1338,8 @@ google.golang.org/genproto v0.0.0-20240814211410-ddb44dafa142 h1:oLiyxGgE+rt22du google.golang.org/genproto v0.0.0-20240814211410-ddb44dafa142/go.mod h1:G11eXq53iI5Q+kyNOmCvnzBaxEA2Q/Ik5Tj7nqBE8j4= google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 h1:wKguEg1hsxI2/L3hUYrpo1RVi48K+uTyzKqprwLXsb8= google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142/go.mod h1:d6be+8HhtEtucleCbxpPW9PA9XwISACu8nvpPqF0BVo= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:pPJltXNxVzT4pK9yD8vR9X75DaWYYmLGMsEvBfFQZzQ= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f h1:cUMEy+8oS78BWIH9OWazBkzbr090Od9tWBNtZHkOhf0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -1373,8 +1375,8 @@ google.golang.org/grpc v1.48.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACu google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= google.golang.org/grpc v1.50.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= -google.golang.org/grpc v1.66.2 h1:3QdXkuq3Bkh7w+ywLdLvM56cmGvQHUMZpiCzt6Rqaoo= -google.golang.org/grpc v1.66.2/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y= +google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E= +google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= 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= diff --git a/simapp/sim_bench_test.go b/simapp/sim_bench_test.go index ba5f02652ef5..cf1361aaf299 100644 --- a/simapp/sim_bench_test.go +++ b/simapp/sim_bench_test.go @@ -3,92 +3,19 @@ package simapp import ( - "os" + "github.com/cosmos/cosmos-sdk/simsx" "testing" - flag "github.com/spf13/pflag" - "github.com/spf13/viper" - "github.com/stretchr/testify/require" - - "cosmossdk.io/log" - - "github.com/cosmos/cosmos-sdk/baseapp" - "github.com/cosmos/cosmos-sdk/client/flags" - "github.com/cosmos/cosmos-sdk/server" - simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" - "github.com/cosmos/cosmos-sdk/testutils/sims" - simtypes "github.com/cosmos/cosmos-sdk/types/simulation" - "github.com/cosmos/cosmos-sdk/x/simulation" simcli "github.com/cosmos/cosmos-sdk/x/simulation/client/cli" ) -var FlagEnableBenchStreamingValue bool - -// Get flags every time the simulator is run -func init() { - flag.BoolVar(&FlagEnableBenchStreamingValue, "EnableStreaming", false, "Enable streaming service") -} - // Profile with: // /usr/local/go/bin/go test -benchmem -run=^$ cosmossdk.io/simapp -bench ^BenchmarkFullAppSimulation$ -Commit=true -cpuprofile cpu.out func BenchmarkFullAppSimulation(b *testing.B) { b.ReportAllocs() config := simcli.NewConfigFromFlags() - config.ChainID = sims.SimAppChainID - - db, dir, logger, skip, err := simtestutil.SetupSimulation(config, "goleveldb-app-sim", "Simulation", simcli.FlagVerboseValue, simcli.FlagEnabledValue) - if err != nil { - b.Fatalf("simulation setup failed: %s", err.Error()) - } - - if skip { - b.Skip("skipping benchmark application simulation") - } - - defer func() { - require.NoError(b, db.Close()) - require.NoError(b, os.RemoveAll(dir)) - }() - - appOptions := viper.New() - appOptions.SetDefault(flags.FlagHome, DefaultNodeHome) - appOptions.SetDefault(server.FlagInvCheckPeriod, simcli.FlagPeriodValue) - - app := NewSimApp(logger, db, nil, true, appOptions, interBlockCacheOpt(), baseapp.SetChainID(sims.SimAppChainID)) - - blockedAddrs, err := BlockedAddresses(app.InterfaceRegistry().SigningContext().AddressCodec()) - require.NoError(b, err) - - // run randomized simulation - simParams, simErr := simulation.SimulateFromSeedX( - b, - log.NewNopLogger(), - os.Stdout, - app.BaseApp, - simtestutil.AppStateFn(app.AppCodec(), app.AuthKeeper.AddressCodec(), app.StakingKeeper.ValidatorAddressCodec(), app.SimulationManager(), app.DefaultGenesis()), - simtypes.RandomAccounts, - simtestutil.SimulationOperations(app, app.AppCodec(), config, app.txConfig), - blockedAddrs, - config, - app.AppCodec(), - app.txConfig.SigningContext().AddressCodec(), - &simulation.DummyLogWriter{}, - ) - - // export state and simParams before the simulation error is checked - if err = simtestutil.CheckExportSimulation(app, config, simParams); err != nil { - b.Fatal(err) - } - - if simErr != nil { - b.Fatal(simErr) - } + config.ChainID = simsx.SimAppChainID - if config.Commit { - db, ok := db.(simtestutil.DBStatsInterface) - if ok { - simtestutil.PrintStats(db) - } - } + simsx.RunWithSeed(b, config, NewSimApp, setupStateFactory, 1, nil) } diff --git a/simapp/sim_test.go b/simapp/sim_test.go index 9cb61c051adf..0fa1a5a472ca 100644 --- a/simapp/sim_test.go +++ b/simapp/sim_test.go @@ -11,6 +11,12 @@ import ( "strings" "sync" "testing" + "time" + + abci "github.com/cometbft/cometbft/api/cometbft/abci/v1" + cmtproto "github.com/cometbft/cometbft/api/cometbft/types/v1" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" corestore "cosmossdk.io/core/store" "cosmossdk.io/log" @@ -20,18 +26,15 @@ import ( "cosmossdk.io/x/feegrant" slashingtypes "cosmossdk.io/x/slashing/types" stakingtypes "cosmossdk.io/x/staking/types" - abci "github.com/cometbft/cometbft/api/cometbft/abci/v1" - cmtproto "github.com/cometbft/cometbft/api/cometbft/types/v1" + "github.com/cosmos/cosmos-sdk/baseapp" servertypes "github.com/cosmos/cosmos-sdk/server/types" + "github.com/cosmos/cosmos-sdk/simsx" simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" - "github.com/cosmos/cosmos-sdk/testutils/sims" sdk "github.com/cosmos/cosmos-sdk/types" simtypes "github.com/cosmos/cosmos-sdk/types/simulation" "github.com/cosmos/cosmos-sdk/x/simulation" simcli "github.com/cosmos/cosmos-sdk/x/simulation/client/cli" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" ) // SimAppChainID hardcoded chainID for simulation @@ -51,32 +54,34 @@ func interBlockCacheOpt() func(*baseapp.BaseApp) { } func TestFullAppSimulation(t *testing.T) { - sims.Run(t, NewSimApp, setupStateFactory) + simsx.Run(t, NewSimApp, setupStateFactory) } -func setupStateFactory(app *SimApp) sims.SimStateFactory { +func setupStateFactory(app *SimApp) simsx.SimStateFactory { blockedAddre, _ := BlockedAddresses(app.interfaceRegistry.SigningContext().AddressCodec()) - return sims.SimStateFactory{ - Codec: app.AppCodec(), - AppStateFn: simtestutil.AppStateFn(app.AppCodec(), app.AuthKeeper.AddressCodec(), app.StakingKeeper.ValidatorAddressCodec(), app.SimulationManager(), app.DefaultGenesis()), - BlockedAddr: blockedAddre, + return simsx.SimStateFactory{ + Codec: app.AppCodec(), + AppStateFn: simtestutil.AppStateFn(app.AppCodec(), app.AuthKeeper.AddressCodec(), app.StakingKeeper.ValidatorAddressCodec(), app.SimulationManager().Modules, app.DefaultGenesis()), + BlockedAddr: blockedAddre, + AccountSource: app.AuthKeeper, + BalanceSource: app.BankKeeper, } } var ( - exportAllModules = []string{} - exportWithValidatorSet = []string{} + exportAllModules []string + exportWithValidatorSet []string ) func TestAppImportExport(t *testing.T) { - sims.Run(t, NewSimApp, setupStateFactory, func(t *testing.T, ti sims.TestInstance[*SimApp]) { + simsx.Run(t, NewSimApp, setupStateFactory, func(t testing.TB, ti simsx.TestInstance[*SimApp], _ []simtypes.Account) { app := ti.App t.Log("exporting genesis...\n") exported, err := app.ExportAppStateAndValidators(false, exportWithValidatorSet, exportAllModules) require.NoError(t, err) t.Log("importing genesis...\n") - newTestInstance := sims.NewSimulationAppInstance(t, ti.Cfg, NewSimApp) + newTestInstance := simsx.NewSimulationAppInstance(t, ti.Cfg, NewSimApp) newApp := newTestInstance.App var genesisState GenesisState require.NoError(t, json.Unmarshal(exported.AppState, &genesisState)) @@ -111,40 +116,40 @@ func TestAppImportExport(t *testing.T) { // set up a new node instance, Init chain from exported genesis // run new instance for n blocks func TestAppSimulationAfterImport(t *testing.T) { - sims.Run(t, NewSimApp, setupStateFactory, func(t *testing.T, ti sims.TestInstance[*SimApp]) { + simsx.Run(t, NewSimApp, setupStateFactory, func(t testing.TB, ti simsx.TestInstance[*SimApp], accs []simtypes.Account) { app := ti.App t.Log("exporting genesis...\n") exported, err := app.ExportAppStateAndValidators(false, exportWithValidatorSet, exportAllModules) require.NoError(t, err) - t.Log("importing genesis...\n") - newTestInstance := sims.NewSimulationAppInstance(t, ti.Cfg, NewSimApp) - newApp := newTestInstance.App - _, err = newApp.InitChain(&abci.InitChainRequest{ - AppStateBytes: exported.AppState, - ChainId: sims.SimAppChainID, - }) - if IsEmptyValidatorSetErr(err) { - t.Skip("Skipping simulation as all validators have been unbonded") - return + importGenesisStateFactory := func(app *SimApp) simsx.SimStateFactory { + return simsx.SimStateFactory{ + Codec: app.AppCodec(), + AppStateFn: func(r *rand.Rand, _ []simtypes.Account, config simtypes.Config) (json.RawMessage, []simtypes.Account, string, time.Time) { + t.Log("importing genesis...\n") + genesisTimestamp := time.Unix(config.GenesisTime, 0) + + _, err = app.InitChain(&abci.InitChainRequest{ + AppStateBytes: exported.AppState, + ChainId: simsx.SimAppChainID, + InitialHeight: exported.Height, + Time: genesisTimestamp, + }) + if IsEmptyValidatorSetErr(err) { + t.Skip("Skipping simulation as all validators have been unbonded") + return nil, nil, "", time.Time{} + } + require.NoError(t, err) + // use accounts from initial run + return exported.AppState, accs, config.ChainID, genesisTimestamp + }, + BlockedAddr: must(BlockedAddresses(app.AuthKeeper.AddressCodec())), + AccountSource: app.AuthKeeper, + BalanceSource: app.BankKeeper, + } } - require.NoError(t, err) - newStateFactory := setupStateFactory(newApp) - _, err = simulation.SimulateFromSeedX( - t, - newTestInstance.AppLogger, - sims.WriteToDebugLog(newTestInstance.AppLogger), - newApp.BaseApp, - newStateFactory.AppStateFn, - simtypes.RandomAccounts, - simtestutil.SimulationOperations(newApp, newApp.AppCodec(), newTestInstance.Cfg, newApp.TxConfig()), - newStateFactory.BlockedAddr, - newTestInstance.Cfg, - newStateFactory.Codec, - newApp.TxConfig().SigningContext().AddressCodec(), - ti.ExecLogWriter, - ) - require.NoError(t, err) + ti.Cfg.InitialBlockHeight = int(exported.Height) + simsx.RunWithSeed(t, ti.Cfg, NewSimApp, importGenesisStateFactory, ti.Cfg.Seed, ti.Cfg.FuzzSeed) }) } @@ -178,7 +183,7 @@ func TestAppStateDeterminism(t *testing.T) { "streaming.abci.stop-node-on-err": true, } others := appOpts - appOpts = sims.AppOptionsFn(func(k string) any { + appOpts = simsx.AppOptionsFn(func(k string) any { if v, ok := m[k]; ok { return v } @@ -190,7 +195,7 @@ func TestAppStateDeterminism(t *testing.T) { var mx sync.Mutex appHashResults := make(map[int64][][]byte) appSimLogger := make(map[int64][]simulation.LogWriter) - captureAndCheckHash := func(t *testing.T, ti sims.TestInstance[*SimApp]) { + captureAndCheckHash := func(t testing.TB, ti simsx.TestInstance[*SimApp], _ []simtypes.Account) { seed, appHash := ti.Cfg.Seed, ti.App.LastCommitID().Hash mx.Lock() otherHashes, execWriters := appHashResults[seed], appSimLogger[seed] @@ -216,7 +221,7 @@ func TestAppStateDeterminism(t *testing.T) { } } // run simulations - sims.RunWithSeeds(t, interBlockCachingAppFactory, setupStateFactory, seeds, []byte{}, captureAndCheckHash) + simsx.RunWithSeeds(t, interBlockCachingAppFactory, setupStateFactory, seeds, []byte{}, captureAndCheckHash) } type ComparableStoreApp interface { @@ -226,7 +231,7 @@ type ComparableStoreApp interface { GetStoreKeys() []storetypes.StoreKey } -func AssertEqualStores(t *testing.T, app ComparableStoreApp, newApp ComparableStoreApp, storeDecoders simtypes.StoreDecoderRegistry, skipPrefixes map[string][][]byte) { +func AssertEqualStores(t testing.TB, app, newApp ComparableStoreApp, storeDecoders simtypes.StoreDecoderRegistry, skipPrefixes map[string][][]byte) { ctxA := app.NewContextLegacy(true, cmtproto.Header{Height: app.LastBlockHeight()}) ctxB := newApp.NewContextLegacy(true, cmtproto.Header{Height: app.LastBlockHeight()}) @@ -264,7 +269,7 @@ func FuzzFullAppSimulation(f *testing.F) { t.Skip() return } - sims.RunWithSeeds( + simsx.RunWithSeeds( t, NewSimApp, setupStateFactory, @@ -273,3 +278,10 @@ func FuzzFullAppSimulation(f *testing.F) { ) }) } + +func must[T any](r T, err error) T { + if err != nil { + panic(err) + } + return r +} diff --git a/simapp/simd/cmd/testnet.go b/simapp/simd/cmd/testnet.go index 116307f63bf2..b7199b4cbafa 100644 --- a/simapp/simd/cmd/testnet.go +++ b/simapp/simd/cmd/testnet.go @@ -353,7 +353,7 @@ func initTestnetFiles( valStr, valPubKeys[i], sdk.NewCoin(args.bondTokenDenom, valTokens), - stakingtypes.NewDescription(nodeDirName, "", "", "", ""), + stakingtypes.NewDescription(nodeDirName, "", "", "", "", stakingtypes.Metadata{}), stakingtypes.NewCommissionRates(math.LegacyOneDec(), math.LegacyOneDec(), math.LegacyOneDec()), math.OneInt(), ) diff --git a/simapp/simd/cmd/testnet_test.go b/simapp/simd/cmd/testnet_test.go index f60a56596c27..f7bea40d28b3 100644 --- a/simapp/simd/cmd/testnet_test.go +++ b/simapp/simd/cmd/testnet_test.go @@ -34,6 +34,7 @@ func Test_TestnetCmd(t *testing.T) { configurator.StakingModule(), configurator.ConsensusModule(), configurator.TxModule(), + configurator.ValidateModule(), configurator.MintModule(), ) var moduleManager *module.Manager diff --git a/simapp/upgrades.go b/simapp/upgrades.go index a4a475490ca2..fc754250b6ce 100644 --- a/simapp/upgrades.go +++ b/simapp/upgrades.go @@ -15,12 +15,12 @@ import ( ) // UpgradeName defines the on-chain upgrade name for the sample SimApp upgrade -// from v0.50.x to v0.51.x +// from v0.52.x to v0.54.x // // NOTE: This upgrade defines a reference implementation of what an upgrade // could look like when an application is migrating from Cosmos SDK version -// v0.50.x to v0.51.x. -const UpgradeName = "v050-to-v051" +// v0.52.x to v0.54.x. +const UpgradeName = "v052-to-v054" func (app SimApp) RegisterUpgradeHandlers() { app.UpgradeKeeper.SetUpgradeHandler( diff --git a/simapp/v2/app_config.go b/simapp/v2/app_config.go index 4f8b0bcb9088..2f1337aec398 100644 --- a/simapp/v2/app_config.go +++ b/simapp/v2/app_config.go @@ -28,6 +28,7 @@ import ( stakingmodulev1 "cosmossdk.io/api/cosmos/staking/module/v1" txconfigv1 "cosmossdk.io/api/cosmos/tx/config/v1" upgrademodulev1 "cosmossdk.io/api/cosmos/upgrade/module/v1" + validatemodulev1 "cosmossdk.io/api/cosmos/validate/module/v1" vestingmodulev1 "cosmossdk.io/api/cosmos/vesting/module/v1" "cosmossdk.io/depinject/appconfig" "cosmossdk.io/x/accounts" @@ -68,12 +69,13 @@ import ( upgradetypes "cosmossdk.io/x/upgrade/types" "github.com/cosmos/cosmos-sdk/runtime" - _ "github.com/cosmos/cosmos-sdk/x/auth" // import for side-effects - _ "github.com/cosmos/cosmos-sdk/x/auth/tx/config" // import for side-effects + _ "github.com/cosmos/cosmos-sdk/x/auth" // import for side-effects + authtxconfig "github.com/cosmos/cosmos-sdk/x/auth/tx/config" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" _ "github.com/cosmos/cosmos-sdk/x/auth/vesting" // import for side-effects vestingtypes "github.com/cosmos/cosmos-sdk/x/auth/vesting/types" genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types" + "github.com/cosmos/cosmos-sdk/x/validate" ) var ( @@ -183,8 +185,22 @@ var ( QueryGasLimit: 100_000, SimulationGasLimit: 100_000, }, + // SkipStoreKeys is an optional list of store keys to skip when constructing the + // module's keeper. This is useful when a module does not have a store key. + SkipStoreKeys: []string{ + authtxconfig.DepinjectModuleName, + validate.ModuleName, + }, }), }, + { + Name: authtxconfig.DepinjectModuleName, // x/auth/tx/config depinject module (not app module), use to provide tx configuration + Config: appconfig.WrapAny(&txconfigv1.Config{}), + }, + { + Name: validate.ModuleName, + Config: appconfig.WrapAny(&validatemodulev1.Module{}), + }, { Name: authtypes.ModuleName, Config: appconfig.WrapAny(&authmodulev1.Module{ @@ -218,10 +234,6 @@ var ( Name: slashingtypes.ModuleName, Config: appconfig.WrapAny(&slashingmodulev1.Module{}), }, - { - Name: "tx", - Config: appconfig.WrapAny(&txconfigv1.Config{}), - }, { Name: genutiltypes.ModuleName, Config: appconfig.WrapAny(&genutilmodulev1.Module{}), @@ -266,10 +278,8 @@ var ( Config: appconfig.WrapAny(&govmodulev1.Module{}), }, { - Name: consensustypes.ModuleName, - Config: appconfig.WrapAny(&consensusmodulev1.Module{ - Authority: "consensus", // TODO remove. - }), + Name: consensustypes.ModuleName, + Config: appconfig.WrapAny(&consensusmodulev1.Module{}), }, { Name: accounts.ModuleName, diff --git a/simapp/v2/app_di.go b/simapp/v2/app_di.go index 733ab1ffc829..43ca45f99aed 100644 --- a/simapp/v2/app_di.go +++ b/simapp/v2/app_di.go @@ -13,7 +13,9 @@ import ( "cosmossdk.io/log" "cosmossdk.io/runtime/v2" "cosmossdk.io/store/v2/root" - consensuskeeper "cosmossdk.io/x/consensus/keeper" + basedepinject "cosmossdk.io/x/accounts/defaults/base/depinject" + lockupdepinject "cosmossdk.io/x/accounts/defaults/lockup/depinject" + multisigdepinject "cosmossdk.io/x/accounts/defaults/multisig/depinject" upgradekeeper "cosmossdk.io/x/upgrade/keeper" "github.com/cosmos/cosmos-sdk/client" @@ -38,8 +40,7 @@ type SimApp[T transaction.Tx] struct { // required keepers during wiring // others keepers are all in the app - UpgradeKeeper *upgradekeeper.Keeper - ConsensusParamsKeeper consensuskeeper.Keeper + UpgradeKeeper *upgradekeeper.Keeper } func init() { @@ -63,14 +64,14 @@ func NewSimApp[T transaction.Tx]( viper *viper.Viper, ) *SimApp[T] { var ( - app = &SimApp[T]{} - appBuilder *runtime.AppBuilder[T] - err error - storeOptions = &root.Options{} + app = &SimApp[T]{} + appBuilder *runtime.AppBuilder[T] + err error // merge the AppConfig and other configuration in one config appConfig = depinject.Configs( AppConfig(), + runtime.DefaultServiceBindings(), depinject.Supply( logger, viper, @@ -120,6 +121,25 @@ func NewSimApp[T transaction.Tx]( codec.ProvideAddressCodec, codec.ProvideProtoCodec, codec.ProvideLegacyAmino, + // inject desired account types: + multisigdepinject.ProvideAccount, + basedepinject.ProvideAccount, + lockupdepinject.ProvideAllLockupAccounts, + + // provide base account options + basedepinject.ProvideSecp256K1PubKey, + // if you want to provide a custom public key you + // can do it from here. + // Example: + // basedepinject.ProvideCustomPubkey[Ed25519PublicKey]() + // + // You can also provide a custom public key with a custom validation function: + // + // basedepinject.ProvideCustomPubKeyAndValidationFunc(func(pub Ed25519PublicKey) error { + // if len(pub.Key) != 64 { + // return fmt.Errorf("invalid pub key size") + // } + // }) ), depinject.Invoke( std.RegisterInterfaces, @@ -128,6 +148,19 @@ func NewSimApp[T transaction.Tx]( ) ) + // the subsection of config that contains the store options (in app.toml [store.options] header) + // is unmarshaled into a store.Options struct and passed to the store builder. + // future work may move this specification and retrieval into store/v2. + // If these options are not specified then default values will be used. + if sub := viper.Sub("store.options"); sub != nil { + storeOptions := &root.Options{} + err := sub.Unmarshal(storeOptions) + if err != nil { + panic(err) + } + appConfig = depinject.Configs(appConfig, depinject.Supply(storeOptions)) + } + if err := depinject.Inject(appConfig, &appBuilder, &app.appCodec, @@ -135,20 +168,11 @@ func NewSimApp[T transaction.Tx]( &app.txConfig, &app.interfaceRegistry, &app.UpgradeKeeper, - &app.ConsensusParamsKeeper, ); err != nil { panic(err) } - var builderOpts []runtime.AppBuilderOption[T] - if sub := viper.Sub("store.options"); sub != nil { - err = sub.Unmarshal(storeOptions) - if err != nil { - panic(err) - } - builderOpts = append(builderOpts, runtime.AppBuilderWithStoreOptions[T](storeOptions)) - } - app.App, err = appBuilder.Build(builderOpts...) + app.App, err = appBuilder.Build() if err != nil { panic(err) } @@ -186,11 +210,6 @@ func (app *SimApp[T]) TxConfig() client.TxConfig { return app.txConfig } -// GetConsensusAuthority gets the consensus authority. -func (app *SimApp[T]) GetConsensusAuthority() string { - return app.ConsensusParamsKeeper.GetAuthority() -} - // GetStore gets the app store. func (app *SimApp[T]) GetStore() any { return app.App.GetStore() diff --git a/simapp/v2/app_test.go b/simapp/v2/app_test.go index a51354e4b3b6..f634d2d67664 100644 --- a/simapp/v2/app_test.go +++ b/simapp/v2/app_test.go @@ -20,6 +20,7 @@ import ( sdkmath "cosmossdk.io/math" serverv2 "cosmossdk.io/server/v2" comettypes "cosmossdk.io/server/v2/cometbft/types" + serverv2store "cosmossdk.io/server/v2/store" "cosmossdk.io/store/v2/db" banktypes "cosmossdk.io/x/bank/types" @@ -36,7 +37,7 @@ func NewTestApp(t *testing.T) (*SimApp[transaction.Tx], context.Context) { logger := log.NewTestLogger(t) vp := viper.New() - vp.Set("store.app-db-backend", string(db.DBTypeGoLevelDB)) + vp.Set(serverv2store.FlagAppDBBackend, string(db.DBTypeGoLevelDB)) vp.Set(serverv2.FlagHome, t.TempDir()) app := NewSimApp[transaction.Tx](logger, vp) diff --git a/simapp/v2/genesis_account_test.go b/simapp/v2/genesis_account_test.go index 5b8339b29c0b..d5f80a702b05 100644 --- a/simapp/v2/genesis_account_test.go +++ b/simapp/v2/genesis_account_test.go @@ -81,7 +81,6 @@ func TestSimGenesisAccountValidate(t *testing.T) { } for _, tc := range testCases { - tc := tc t.Run(tc.name, func(t *testing.T) { require.Equal(t, tc.wantErr, tc.sga.Validate() != nil) }) diff --git a/simapp/v2/go.mod b/simapp/v2/go.mod index e4003e4c9012..484d0de1e4ee 100644 --- a/simapp/v2/go.mod +++ b/simapp/v2/go.mod @@ -3,9 +3,9 @@ module cosmossdk.io/simapp/v2 go 1.23.1 require ( - cosmossdk.io/api v0.7.5 + cosmossdk.io/api v0.7.6 cosmossdk.io/client/v2 v2.0.0-00010101000000-000000000000 - cosmossdk.io/core v1.0.0-alpha.2 + cosmossdk.io/core v1.0.0-alpha.4 cosmossdk.io/depinject v1.0.0 cosmossdk.io/log v1.4.1 cosmossdk.io/math v1.3.0 @@ -14,7 +14,7 @@ require ( cosmossdk.io/server/v2/cometbft v0.0.0-00010101000000-000000000000 cosmossdk.io/store/v2 v2.0.0 cosmossdk.io/tools/confix v0.0.0-00010101000000-000000000000 - cosmossdk.io/x/accounts v0.0.0-20240226161501-23359a0b6d91 + cosmossdk.io/x/accounts v0.0.0-20240913065641-0064ccbce64e cosmossdk.io/x/authz v0.0.0-00010101000000-000000000000 cosmossdk.io/x/bank v0.0.0-20240226161501-23359a0b6d91 cosmossdk.io/x/circuit v0.0.0-20230613133644-0a778132a60f @@ -32,9 +32,9 @@ require ( cosmossdk.io/x/staking v0.0.0-00010101000000-000000000000 cosmossdk.io/x/upgrade v0.0.0-20230613133644-0a778132a60f github.com/cometbft/cometbft v1.0.0-rc1.0.20240908111210-ab0be101882f - github.com/cosmos/cosmos-db v1.0.3-0.20240911104526-ddc3f09bfc22 // indirect // this version is not used as it is always replaced by the latest Cosmos SDK version github.com/cosmos/cosmos-sdk v0.53.0 + github.com/spf13/cast v1.7.0 // indirect github.com/spf13/cobra v1.8.1 github.com/spf13/pflag v1.0.5 github.com/spf13/viper v1.19.0 @@ -42,6 +42,12 @@ require ( google.golang.org/protobuf v1.34.2 ) +require ( + cosmossdk.io/x/accounts/defaults/base v0.0.0-00010101000000-000000000000 + cosmossdk.io/x/accounts/defaults/lockup v0.0.0-00010101000000-000000000000 + cosmossdk.io/x/accounts/defaults/multisig v0.0.0-00010101000000-000000000000 +) + require ( buf.build/gen/go/cometbft/cometbft/protocolbuffers/go v1.34.2-20240701160653-fedbb9acfd2f.2 // indirect buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.34.2-20240130113600-88ef6483f90f.2 // indirect @@ -52,16 +58,14 @@ require ( cloud.google.com/go/iam v1.1.13 // indirect cloud.google.com/go/storage v1.43.0 // indirect cosmossdk.io/collections v0.4.0 // indirect - cosmossdk.io/core/testing v0.0.0-00010101000000-000000000000 // indirect + cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29 // indirect cosmossdk.io/errors v1.0.1 // indirect cosmossdk.io/errors/v2 v2.0.0-20240731132947-df72853b3ca5 // indirect - cosmossdk.io/schema v0.2.0 // indirect + cosmossdk.io/schema v0.3.1-0.20240930054013-7c6e0388a3f9 // indirect cosmossdk.io/server/v2/appmanager v0.0.0-20240802110823-cffeedff643d // indirect cosmossdk.io/server/v2/stf v0.0.0-20240708142107-25e99c54bac1 // indirect - cosmossdk.io/store v1.1.1-0.20240418092142-896cdf1971bc // indirect - cosmossdk.io/x/accounts/defaults/lockup v0.0.0-20240417181816-5e7aae0db1f5 // indirect - cosmossdk.io/x/accounts/defaults/multisig v0.0.0-00010101000000-000000000000 // indirect - cosmossdk.io/x/tx v0.13.4 // indirect + cosmossdk.io/store v1.1.1 // indirect + cosmossdk.io/x/tx v0.13.5 // indirect filippo.io/edwards25519 v1.1.0 // indirect github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect github.com/99designs/keyring v1.2.2 // indirect @@ -87,6 +91,7 @@ require ( github.com/cometbft/cometbft-db v0.15.0 // indirect github.com/cometbft/cometbft/api v1.0.0-rc.1 // indirect github.com/cosmos/btcutil v1.0.5 // indirect + github.com/cosmos/cosmos-db v1.0.3-0.20240911104526-ddc3f09bfc22 // indirect github.com/cosmos/cosmos-proto v1.0.0-beta.5 // indirect github.com/cosmos/crypto v0.1.2 // indirect github.com/cosmos/go-bip39 v1.0.0 // indirect @@ -148,7 +153,7 @@ require ( github.com/hashicorp/hcl v1.0.0 // indirect github.com/hashicorp/yamux v0.1.1 // indirect github.com/hdevalence/ed25519consensus v0.2.0 // indirect - github.com/huandu/skiplist v1.2.0 // indirect + github.com/huandu/skiplist v1.2.1 // indirect github.com/iancoleman/strcase v0.3.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect @@ -179,21 +184,20 @@ require ( github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/client_golang v1.20.3 // indirect + github.com/prometheus/client_golang v1.20.4 // indirect github.com/prometheus/client_model v0.6.1 // indirect - github.com/prometheus/common v0.59.1 // indirect + github.com/prometheus/common v0.60.0 // indirect github.com/prometheus/procfs v0.15.1 // indirect github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect github.com/rivo/uniseg v0.2.0 // indirect github.com/rogpeppe/go-internal v1.12.0 // indirect - github.com/rs/cors v1.11.0 // indirect + github.com/rs/cors v1.11.1 // indirect github.com/rs/zerolog v1.33.0 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect github.com/sasha-s/go-deadlock v0.3.5 // indirect github.com/sourcegraph/conc v0.3.0 // indirect github.com/spf13/afero v1.11.0 // indirect - github.com/spf13/cast v1.7.0 // indirect github.com/subosito/gotenv v1.6.0 // indirect github.com/supranational/blst v0.3.13 // indirect github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d // indirect @@ -216,7 +220,7 @@ require ( golang.org/x/exp v0.0.0-20240531132922-fd00a4e0eefc // indirect golang.org/x/mod v0.17.0 // indirect golang.org/x/net v0.29.0 // indirect - golang.org/x/oauth2 v0.22.0 // indirect + golang.org/x/oauth2 v0.23.0 // indirect golang.org/x/sync v0.8.0 // indirect golang.org/x/sys v0.25.0 // indirect golang.org/x/term v0.24.0 // indirect @@ -226,8 +230,8 @@ require ( google.golang.org/api v0.192.0 // indirect google.golang.org/genproto v0.0.0-20240814211410-ddb44dafa142 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect - google.golang.org/grpc v1.66.2 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f // indirect + google.golang.org/grpc v1.67.1 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect gotest.tools/v3 v3.5.1 // indirect @@ -248,6 +252,7 @@ replace ( cosmossdk.io/collections => ../../collections cosmossdk.io/tools/confix => ../../tools/confix cosmossdk.io/x/accounts => ../../x/accounts + cosmossdk.io/x/accounts/defaults/base => ../../x/accounts/defaults/base cosmossdk.io/x/accounts/defaults/lockup => ../../x/accounts/defaults/lockup cosmossdk.io/x/accounts/defaults/multisig => ../../x/accounts/defaults/multisig cosmossdk.io/x/authz => ../../x/authz @@ -286,7 +291,6 @@ replace ( // server v2 integration replace ( cosmossdk.io/api => ../../api - cosmossdk.io/core/testing => ../../core/testing cosmossdk.io/runtime/v2 => ../../runtime/v2 cosmossdk.io/server/v2 => ../../server/v2 cosmossdk.io/server/v2/appmanager => ../../server/v2/appmanager diff --git a/simapp/v2/go.sum b/simapp/v2/go.sum index ede14d58a04e..b0eca7fdef2e 100644 --- a/simapp/v2/go.sum +++ b/simapp/v2/go.sum @@ -192,8 +192,10 @@ cloud.google.com/go/webrisk v1.4.0/go.mod h1:Hn8X6Zr+ziE2aNd8SliSDWpEnSS1u4R9+xX cloud.google.com/go/webrisk v1.5.0/go.mod h1:iPG6fr52Tv7sGk0H6qUFzmL3HHZev1htXuWDEEsqMTg= cloud.google.com/go/workflows v1.6.0/go.mod h1:6t9F5h/unJz41YqfBmqSASJSXccBLtD1Vwf+KmJENM0= cloud.google.com/go/workflows v1.7.0/go.mod h1:JhSrZuVZWuiDfKEFxU0/F1PQjmpnpcoISEXH2bcHC3M= -cosmossdk.io/core v1.0.0-alpha.2 h1:epU0Xwces4Rgl5bMhHHkXGaGDcyucNGlC/JDH+Suckg= -cosmossdk.io/core v1.0.0-alpha.2/go.mod h1:abgLjeFLhtuKIYZWSPlVUgQBrKObO7ULV35KYfexE90= +cosmossdk.io/core v1.0.0-alpha.4 h1:9iuroT9ejDYETCsGkzkvs/wAY/5UFl7nCIINFRxyMJY= +cosmossdk.io/core v1.0.0-alpha.4/go.mod h1:3u9cWq1FAVtiiCrDPpo4LhR+9V6k/ycSG4/Y/tREWCY= +cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29 h1:NxxUo0GMJUbIuVg0R70e3cbn9eFTEuMr7ev1AFvypdY= +cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29/go.mod h1:8s2tPeJtSiQuoyPmr2Ag7meikonISO4Fv4MoO8+ORrs= cosmossdk.io/depinject v1.0.0 h1:dQaTu6+O6askNXO06+jyeUAnF2/ssKwrrszP9t5q050= cosmossdk.io/depinject v1.0.0/go.mod h1:zxK/h3HgHoA/eJVtiSsoaRaRA2D5U4cJ5thIG4ssbB8= cosmossdk.io/errors v1.0.1 h1:bzu+Kcr0kS/1DuPBtUFdWjzLqyUuCiyHjyJB6srBV/0= @@ -204,8 +206,8 @@ cosmossdk.io/log v1.4.1 h1:wKdjfDRbDyZRuWa8M+9nuvpVYxrEOwbD/CA8hvhU8QM= cosmossdk.io/log v1.4.1/go.mod h1:k08v0Pyq+gCP6phvdI6RCGhLf/r425UT6Rk/m+o74rU= cosmossdk.io/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE= cosmossdk.io/math v1.3.0/go.mod h1:vnRTxewy+M7BtXBNFybkuhSH4WfedVAAnERHgVFhp3k= -cosmossdk.io/schema v0.2.0 h1:UH5CR1DqUq8yP+5Np8PbvG4YX0zAUsTN2Qk6yThmfMk= -cosmossdk.io/schema v0.2.0/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= +cosmossdk.io/schema v0.3.1-0.20240930054013-7c6e0388a3f9 h1:DmOoS/1PeY6Ih0hAVlJ69kLMUrLV+TCbfICrZtB1vdU= +cosmossdk.io/schema v0.3.1-0.20240930054013-7c6e0388a3f9/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= @@ -592,8 +594,8 @@ github.com/hdevalence/ed25519consensus v0.2.0/go.mod h1:w3BHWjwJbFU29IRHL1Iqkw3s github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/huandu/go-assert v1.1.5 h1:fjemmA7sSfYHJD7CUqs9qTwwfdNAx7/j2/ZlHXzNB3c= github.com/huandu/go-assert v1.1.5/go.mod h1:yOLvuqZwmcHIC5rIzrBhT7D3Q9c3GFnd0JrPVhn/06U= -github.com/huandu/skiplist v1.2.0 h1:gox56QD77HzSC0w+Ws3MH3iie755GBJU1OER3h5VsYw= -github.com/huandu/skiplist v1.2.0/go.mod h1:7v3iFjLcSAzO4fN5B8dvebvo/qsfumiLiDXMrPiHF9w= +github.com/huandu/skiplist v1.2.1 h1:dTi93MgjwErA/8idWTzIw4Y1kZsMWx35fmI2c8Rij7w= +github.com/huandu/skiplist v1.2.1/go.mod h1:7v3iFjLcSAzO4fN5B8dvebvo/qsfumiLiDXMrPiHF9w= github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI= github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= @@ -723,8 +725,8 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= -github.com/prometheus/client_golang v1.20.3 h1:oPksm4K8B+Vt35tUhw6GbSNSgVlVSBH0qELP/7u83l4= -github.com/prometheus/client_golang v1.20.3/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_golang v1.20.4 h1:Tgh3Yr67PaOv/uTqloMsCEdeuFTatm5zIq5+qNN23vI= +github.com/prometheus/client_golang v1.20.4/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -733,8 +735,8 @@ github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= -github.com/prometheus/common v0.59.1 h1:LXb1quJHWm1P6wq/U824uxYi4Sg0oGvNeUm1z5dJoX0= -github.com/prometheus/common v0.59.1/go.mod h1:GpWM7dewqmVYcd7SmRaiWVe9SSqjf0UrwnYnpEZNuT0= +github.com/prometheus/common v0.60.0 h1:+V9PAREWNvJMAuJ1x1BaWl9dewMW4YrHZQbx0sJNllA= +github.com/prometheus/common v0.60.0/go.mod h1:h0LYf1R1deLSKtD4Vdg8gy4RuOvENW2J/h19V5NADQw= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/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= @@ -749,8 +751,8 @@ github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= -github.com/rs/cors v1.11.0 h1:0B9GE/r9Bc2UxRMMtymBkHTenPkHDv0CW4Y98GBY+po= -github.com/rs/cors v1.11.0/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= +github.com/rs/cors v1.11.1 h1:eU3gRzXLRK57F5rKMGMZURNdIG4EoAmX8k94r9wXWHA= +github.com/rs/cors v1.11.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8= github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= @@ -985,8 +987,8 @@ golang.org/x/oauth2 v0.0.0-20220822191816-0ebed06d0094/go.mod h1:h4gKUeWbJ4rQPri golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= golang.org/x/oauth2 v0.1.0/go.mod h1:G9FE4dLTsbXUu90h/Pf85g4w1D+SSAgR+q46nJZ8M4A= -golang.org/x/oauth2 v0.22.0 h1:BzDx2FehcG7jJwgWLELCdmLuxk2i+x9UDpSiss2u0ZA= -golang.org/x/oauth2 v0.22.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/oauth2 v0.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs= +golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= 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= @@ -1340,8 +1342,8 @@ google.golang.org/genproto v0.0.0-20240814211410-ddb44dafa142 h1:oLiyxGgE+rt22du google.golang.org/genproto v0.0.0-20240814211410-ddb44dafa142/go.mod h1:G11eXq53iI5Q+kyNOmCvnzBaxEA2Q/Ik5Tj7nqBE8j4= google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 h1:wKguEg1hsxI2/L3hUYrpo1RVi48K+uTyzKqprwLXsb8= google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142/go.mod h1:d6be+8HhtEtucleCbxpPW9PA9XwISACu8nvpPqF0BVo= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:pPJltXNxVzT4pK9yD8vR9X75DaWYYmLGMsEvBfFQZzQ= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f h1:cUMEy+8oS78BWIH9OWazBkzbr090Od9tWBNtZHkOhf0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -1377,8 +1379,8 @@ google.golang.org/grpc v1.48.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACu google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= google.golang.org/grpc v1.50.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= -google.golang.org/grpc v1.66.2 h1:3QdXkuq3Bkh7w+ywLdLvM56cmGvQHUMZpiCzt6Rqaoo= -google.golang.org/grpc v1.66.2/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y= +google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E= +google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= 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= diff --git a/simapp/v2/simdv2/cmd/commands.go b/simapp/v2/simdv2/cmd/commands.go index d58619170e0d..addc7eeb768b 100644 --- a/simapp/v2/simdv2/cmd/commands.go +++ b/simapp/v2/simdv2/cmd/commands.go @@ -15,6 +15,7 @@ import ( runtimev2 "cosmossdk.io/runtime/v2" serverv2 "cosmossdk.io/server/v2" "cosmossdk.io/server/v2/api/grpc" + "cosmossdk.io/server/v2/api/telemetry" "cosmossdk.io/server/v2/cometbft" "cosmossdk.io/server/v2/store" "cosmossdk.io/simapp/v2" @@ -74,9 +75,14 @@ func initRootCmd[T transaction.Tx]( newApp, logger, initServerConfig(), - cometbft.New(&genericTxDecoder[T]{txConfig}, cometbft.DefaultServerOptions[T]()), + cometbft.New( + &genericTxDecoder[T]{txConfig}, + initCometOptions[T](), + initCometConfig(), + ), grpc.New[T](), store.New[T](newApp), + telemetry.New[T](), ); err != nil { panic(err) } diff --git a/simapp/v2/simdv2/cmd/config.go b/simapp/v2/simdv2/cmd/config.go index c7f6b707c89c..51a7adb178e9 100644 --- a/simapp/v2/simdv2/cmd/config.go +++ b/simapp/v2/simdv2/cmd/config.go @@ -2,8 +2,13 @@ package cmd import ( "strings" + "time" + cmtcfg "github.com/cometbft/cometbft/config" + + "cosmossdk.io/core/transaction" serverv2 "cosmossdk.io/server/v2" + "cosmossdk.io/server/v2/cometbft" clientconfig "github.com/cosmos/cosmos-sdk/client/config" "github.com/cosmos/cosmos-sdk/crypto/keyring" @@ -68,3 +73,34 @@ func initServerConfig() serverv2.ServerConfig { return serverCfg } + +// initCometConfig helps to override default comet config template and configs. +func initCometConfig() cometbft.CfgOption { + cfg := cmtcfg.DefaultConfig() + + // display only warn logs by default except for p2p and state + cfg.LogLevel = "*:warn,p2p:info,state:info" + // increase block timeout + cfg.Consensus.TimeoutCommit = 5 * time.Second + // overwrite default pprof listen address + cfg.RPC.PprofListenAddress = "localhost:6060" + + return cometbft.OverwriteDefaultConfigTomlConfig(cfg) +} + +func initCometOptions[T transaction.Tx]() cometbft.ServerOptions[T] { + serverOptions := cometbft.DefaultServerOptions[T]() + + // overwrite app mempool, using max-txs option + // serverOptions.Mempool = func(cfg map[string]any) mempool.Mempool[T] { + // if maxTxs := cast.ToInt(cfg[cometbft.FlagMempoolMaxTxs]); maxTxs >= 0 { + // return sdkmempool.NewSenderNonceMempool( + // sdkmempool.SenderNonceMaxTxOpt(maxTxs), + // ) + // } + + // return mempool.NoOpMempool[T]{} + // } + + return serverOptions +} diff --git a/simapp/v2/simdv2/cmd/root_di.go b/simapp/v2/simdv2/cmd/root_di.go index fd5b62b9384b..1ad834b53a5a 100644 --- a/simapp/v2/simdv2/cmd/root_di.go +++ b/simapp/v2/simdv2/cmd/root_di.go @@ -37,6 +37,7 @@ func NewRootCmd[T transaction.Tx]() *cobra.Command { if err := depinject.Inject( depinject.Configs( simapp.AppConfig(), + runtime.DefaultServiceBindings(), depinject.Supply(log.NewNopLogger()), depinject.Provide( codec.ProvideInterfaceRegistry, diff --git a/simapp/v2/simdv2/cmd/testnet.go b/simapp/v2/simdv2/cmd/testnet.go index 99dfb9459a13..ae01310f9151 100644 --- a/simapp/v2/simdv2/cmd/testnet.go +++ b/simapp/v2/simdv2/cmd/testnet.go @@ -24,6 +24,7 @@ import ( "cosmossdk.io/server/v2/cometbft" "cosmossdk.io/server/v2/store" banktypes "cosmossdk.io/x/bank/types" + bankv2types "cosmossdk.io/x/bank/v2/types" stakingtypes "cosmossdk.io/x/staking/types" "github.com/cosmos/cosmos-sdk/client" @@ -295,7 +296,7 @@ func initTestnetFiles[T transaction.Tx]( valStr, valPubKeys[i], sdk.NewCoin(args.bondTokenDenom, valTokens), - stakingtypes.NewDescription(nodeDirName, "", "", "", ""), + stakingtypes.NewDescription(nodeDirName, "", "", "", "", stakingtypes.Metadata{}), stakingtypes.NewCommissionRates(math.LegacyOneDec(), math.LegacyOneDec(), math.LegacyOneDec()), math.OneInt(), ) @@ -402,6 +403,13 @@ func initGenFiles[T transaction.Tx]( } appGenState[banktypes.ModuleName] = clientCtx.Codec.MustMarshalJSON(&bankGenState) + var bankV2GenState bankv2types.GenesisState + clientCtx.Codec.MustUnmarshalJSON(appGenState[bankv2types.ModuleName], &bankV2GenState) + if len(bankV2GenState.Balances) == 0 { + bankV2GenState = getBankV2GenesisFromV1(bankGenState) + } + appGenState[bankv2types.ModuleName] = clientCtx.Codec.MustMarshalJSON(&bankV2GenState) + appGenStateJSON, err := json.MarshalIndent(appGenState, "", " ") if err != nil { return err @@ -504,3 +512,16 @@ func writeFile(name, dir string, contents []byte) error { return os.WriteFile(file, contents, 0o600) } + +// getBankV2GenesisFromV1 clones bank/v1 state to bank/v2 +// since we not migrate yet +// TODO: Remove +func getBankV2GenesisFromV1(v1GenesisState banktypes.GenesisState) bankv2types.GenesisState { + var v2GenesisState bankv2types.GenesisState + for _, balance := range v1GenesisState.Balances { + v2Balance := bankv2types.Balance(balance) + v2GenesisState.Balances = append(v2GenesisState.Balances, v2Balance) + v2GenesisState.Supply = v2GenesisState.Supply.Add(balance.Coins...) + } + return v2GenesisState +} diff --git a/simapp/v2/upgrades.go b/simapp/v2/upgrades.go index 48d557eedb41..2145196fa86d 100644 --- a/simapp/v2/upgrades.go +++ b/simapp/v2/upgrades.go @@ -14,12 +14,12 @@ import ( ) // UpgradeName defines the on-chain upgrade name for the sample SimApp upgrade -// from v0.50.x to v0.51.x +// from v0.52.x to v2 // // NOTE: This upgrade defines a reference implementation of what an upgrade // could look like when an application is migrating from Cosmos SDK version -// v0.50.x to v0.51.x. -const UpgradeName = "v050-to-v051" +// v0.52.x to v2. +const UpgradeName = "v052-to-v2" func (app *SimApp[T]) RegisterUpgradeHandlers() { app.UpgradeKeeper.SetUpgradeHandler( diff --git a/simsx/README.md b/simsx/README.md new file mode 100644 index 000000000000..3e2d9146ce42 --- /dev/null +++ b/simsx/README.md @@ -0,0 +1,47 @@ +# Simsx + +This package introduces some new helper types to simplify message construction for simulations (sims). The focus is on better dev UX for new message factories. +Technically, they are adapters that build upon the existing sims framework. + +## [Message factory](https://github.com/cosmos/cosmos-sdk/blob/main/simsx/msg_factory.go) + +Simple functions as factories for dedicated sdk.Msgs. They have access to the context, reporter and test data environment. For example: + +```go +func MsgSendFactory() simsx.SimMsgFactoryFn[*types.MsgSend] { + return func(ctx context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter) ([]simsx.SimAccount, *types.MsgSend) { + from := testData.AnyAccount(reporter, simsx.WithSpendableBalance()) + to := testData.AnyAccount(reporter, simsx.ExcludeAccounts(from)) + coins := from.LiquidBalance().RandSubsetCoins(reporter, simsx.WithSendEnabledCoins()) + return []simsx.SimAccount{from}, types.NewMsgSend(from.AddressBech32, to.AddressBech32, coins) + } +} +``` + +## [Sims registry](https://github.com/cosmos/cosmos-sdk/blob/main/simsx/registry.go) + +A new helper to register message factories with a default weight value. They can be overwritten by a parameters file as before. The registry is passed to the AppModule type. For example: + +```go +func (am AppModule) WeightedOperationsX(weights simsx.WeightSource, reg simsx.Registry) { + reg.Add(weights.Get("msg_send", 100), simulation.MsgSendFactory()) + reg.Add(weights.Get("msg_multisend", 10), simulation.MsgMultiSendFactory()) +} +``` + +## [Reporter](https://github.com/cosmos/cosmos-sdk/blob/main/simsx/reporter.go) + +The reporter is a flow control structure that can be used in message factories to skip execution at any point. The idea is similar to the testing.T Skip in Go stdlib. Internally, it converts skip, success and failure events to legacy sim messages. +The reporter also provides some capability to print an execution summary. +It is also used to interact with the test data environment to not have errors checked all the time. +Message factories may want to abort early via + +```go +if reporter.IsSkipped() { + return nil, nil +} +``` + +## [Test data environment](https://github.com/cosmos/cosmos-sdk/blob/main/simsx/environment.go) + +The test data environment provides simple access to accounts and other test data used in most message factories. It also encapsulates some app internals like bank keeper or address codec. diff --git a/simsx/common_test.go b/simsx/common_test.go new file mode 100644 index 000000000000..43fcd7d41860 --- /dev/null +++ b/simsx/common_test.go @@ -0,0 +1,161 @@ +package simsx + +import ( + "context" + "math/rand" + + "github.com/cosmos/gogoproto/proto" + + coretransaction "cosmossdk.io/core/transaction" + "cosmossdk.io/x/tx/signing" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/codec/address" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" + "github.com/cosmos/cosmos-sdk/std" + "github.com/cosmos/cosmos-sdk/testutil/testdata" + sdk "github.com/cosmos/cosmos-sdk/types" + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" + "github.com/cosmos/cosmos-sdk/x/auth/tx" +) + +// SimAccountFixture testing only +func SimAccountFixture(mutators ...func(account *SimAccount)) SimAccount { + r := rand.New(rand.NewSource(1)) + acc := SimAccount{ + Account: simtypes.RandomAccounts(r, 1)[0], + } + acc.liquidBalance = NewSimsAccountBalance(&acc, r, sdk.NewCoins(sdk.NewInt64Coin(sdk.DefaultBondDenom, 1_000_000_000))) + for _, mutator := range mutators { + mutator(&acc) + } + return acc +} + +// MemoryAccountSource testing only +func MemoryAccountSource(srcs ...SimAccount) AccountSourceFn { + accs := make(map[string]FakeAccountI, len(srcs)) + for _, src := range srcs { + accs[src.AddressBech32] = FakeAccountI{SimAccount: src, id: 1, seq: 2} + } + return func(ctx context.Context, addr sdk.AccAddress) sdk.AccountI { + return accs[addr.String()] + } +} + +// testing only +func txConfig() client.TxConfig { + ir := must(codectypes.NewInterfaceRegistryWithOptions(codectypes.InterfaceRegistryOptions{ + ProtoFiles: proto.HybridResolver, + SigningOptions: signing.Options{ + AddressCodec: address.NewBech32Codec("cosmos"), + ValidatorAddressCodec: address.NewBech32Codec("cosmosvaloper"), + }, + })) + std.RegisterInterfaces(ir) + ir.RegisterImplementations((*coretransaction.Msg)(nil), &testdata.TestMsg{}) + protoCodec := codec.NewProtoCodec(ir) + signingCtx := protoCodec.InterfaceRegistry().SigningContext() + return tx.NewTxConfig(protoCodec, signingCtx.AddressCodec(), signingCtx.ValidatorAddressCodec(), tx.DefaultSignModes) +} + +var _ AppEntrypoint = SimDeliverFn(nil) + +type ( + AppEntrypointFn = SimDeliverFn + SimDeliverFn func(_txEncoder sdk.TxEncoder, tx sdk.Tx) (sdk.GasInfo, *sdk.Result, error) +) + +func (m SimDeliverFn) SimDeliver(txEncoder sdk.TxEncoder, tx sdk.Tx) (sdk.GasInfo, *sdk.Result, error) { + return m(txEncoder, tx) +} + +var _ AccountSource = AccountSourceFn(nil) + +type AccountSourceFn func(ctx context.Context, addr sdk.AccAddress) sdk.AccountI + +func (a AccountSourceFn) GetAccount(ctx context.Context, addr sdk.AccAddress) sdk.AccountI { + return a(ctx, addr) +} + +var _ sdk.AccountI = &FakeAccountI{} + +type FakeAccountI struct { + SimAccount + id, seq uint64 +} + +func (m FakeAccountI) GetAddress() sdk.AccAddress { + return m.Address +} + +func (m FakeAccountI) GetPubKey() cryptotypes.PubKey { + return m.PubKey +} + +func (m FakeAccountI) GetAccountNumber() uint64 { + return m.id +} + +func (m FakeAccountI) GetSequence() uint64 { + return m.seq +} + +func (m FakeAccountI) Reset() { + panic("implement me") +} + +func (m FakeAccountI) String() string { + panic("implement me") +} + +func (m FakeAccountI) ProtoMessage() { + panic("implement me") +} + +func (m FakeAccountI) SetAddress(address sdk.AccAddress) error { + panic("implement me") +} + +func (m FakeAccountI) SetPubKey(key cryptotypes.PubKey) error { + panic("implement me") +} + +func (m FakeAccountI) SetAccountNumber(u uint64) error { + panic("implement me") +} + +func (m FakeAccountI) SetSequence(u uint64) error { + panic("implement me") +} + +var _ AccountSourceX = &MockAccountSourceX{} + +// MockAccountSourceX mock impl for testing only +type MockAccountSourceX struct { + GetAccountFn func(ctx context.Context, addr sdk.AccAddress) sdk.AccountI + GetModuleAddressFn func(moduleName string) sdk.AccAddress +} + +func (m MockAccountSourceX) GetAccount(ctx context.Context, addr sdk.AccAddress) sdk.AccountI { + if m.GetAccountFn == nil { + panic("not expected to be called") + } + return m.GetAccountFn(ctx, addr) +} + +func (m MockAccountSourceX) GetModuleAddress(moduleName string) sdk.AccAddress { + if m.GetModuleAddressFn == nil { + panic("not expected to be called") + } + return m.GetModuleAddressFn(moduleName) +} + +func must[T any](r T, err error) T { + if err != nil { + panic(err) + } + return r +} diff --git a/simsx/context.go b/simsx/context.go new file mode 100644 index 000000000000..13bdc10efad3 --- /dev/null +++ b/simsx/context.go @@ -0,0 +1,17 @@ +package simsx + +import ( + "context" + "time" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// BlockTime read header block time from sdk context or sims context key if not present +func BlockTime(ctx context.Context) time.Time { + sdkCtx, ok := sdk.TryUnwrapSDKContext(ctx) + if ok { + return sdkCtx.BlockTime() + } + return ctx.Value("sims.header.time").(time.Time) +} diff --git a/simsx/delivery.go b/simsx/delivery.go new file mode 100644 index 000000000000..f67c9cc79b88 --- /dev/null +++ b/simsx/delivery.go @@ -0,0 +1,98 @@ +package simsx + +import ( + "context" + "errors" + "fmt" + "math/rand" + + "github.com/cosmos/cosmos-sdk/client" + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" + "github.com/cosmos/cosmos-sdk/testutil/sims" + sdk "github.com/cosmos/cosmos-sdk/types" + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" +) + +type ( + // AppEntrypoint is an alias to the simtype interface + AppEntrypoint = simtypes.AppEntrypoint + + AccountSource interface { + GetAccount(ctx context.Context, addr sdk.AccAddress) sdk.AccountI + } + // SimDeliveryResultHandler processes the delivery response error. Some sims are supposed to fail and expect an error. + // An unhandled error returned indicates a failure + SimDeliveryResultHandler func(error) error +) + +// DeliverSimsMsg delivers a simulation message by creating and signing a mock transaction, +// then delivering it to the application through the specified entrypoint. It returns a legacy +// operation message representing the result of the delivery. +// +// The function takes the following parameters: +// - reporter: SimulationReporter - Interface for reporting the result of the delivery +// - r: *rand.Rand - Random number generator used for creating the mock transaction +// - app: AppEntrypoint - Entry point for delivering the simulation transaction to the application +// - txGen: client.TxConfig - Configuration for generating transactions +// - ak: AccountSource - Source for retrieving accounts +// - msg: sdk.Msg - The simulation message to be delivered +// - ctx: sdk.Context - The simulation context +// - chainID: string - The chain ID +// - senders: ...SimAccount - Accounts from which to send the simulation message +// +// The function returns a simtypes.OperationMsg, which is a legacy representation of the result +// of the delivery. +func DeliverSimsMsg( + ctx context.Context, + reporter SimulationReporter, + app AppEntrypoint, + r *rand.Rand, + txGen client.TxConfig, + ak AccountSource, + chainID string, + msg sdk.Msg, + deliveryResultHandler SimDeliveryResultHandler, + senders ...SimAccount, +) simtypes.OperationMsg { + if reporter.IsSkipped() { + return reporter.ToLegacyOperationMsg() + } + if len(senders) == 0 { + reporter.Fail(errors.New("no senders"), "encoding TX") + return reporter.ToLegacyOperationMsg() + } + accountNumbers := make([]uint64, len(senders)) + sequenceNumbers := make([]uint64, len(senders)) + for i := 0; i < len(senders); i++ { + acc := ak.GetAccount(ctx, senders[i].Address) + accountNumbers[i] = acc.GetAccountNumber() + sequenceNumbers[i] = acc.GetSequence() + } + fees := senders[0].LiquidBalance().RandFees() + tx, err := sims.GenSignedMockTx( + r, + txGen, + []sdk.Msg{msg}, + fees, + sims.DefaultGenTxGas, + chainID, + accountNumbers, + sequenceNumbers, + Collect(senders, func(a SimAccount) cryptotypes.PrivKey { return a.PrivKey })..., + ) + if err != nil { + reporter.Fail(err, "encoding TX") + return reporter.ToLegacyOperationMsg() + } + _, _, err = app.SimDeliver(txGen.TxEncoder(), tx) + if err2 := deliveryResultHandler(err); err2 != nil { + var comment string + for _, msg := range tx.GetMsgs() { + comment += fmt.Sprintf("%#v", msg) + } + reporter.Fail(err2, fmt.Sprintf("delivering tx with msgs: %s", comment)) + return reporter.ToLegacyOperationMsg() + } + reporter.Success(msg) + return reporter.ToLegacyOperationMsg() +} diff --git a/simsx/delivery_test.go b/simsx/delivery_test.go new file mode 100644 index 000000000000..627841fcb9af --- /dev/null +++ b/simsx/delivery_test.go @@ -0,0 +1,74 @@ +package simsx + +import ( + "errors" + "math/rand" + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/cosmos/cosmos-sdk/testutil/testdata" + sdk "github.com/cosmos/cosmos-sdk/types" + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" +) + +func TestDeliverSimsMsg(t *testing.T) { + var ( + sender = SimAccountFixture() + ak = MemoryAccountSource(sender) + myMsg = testdata.NewTestMsg(sender.Address) + txConfig = txConfig() + r = rand.New(rand.NewSource(1)) + ctx sdk.Context + ) + noopResultHandler := func(err error) error { return err } + specs := map[string]struct { + app AppEntrypoint + reporter func() SimulationReporter + deliveryResultHandler SimDeliveryResultHandler + errDeliveryResultHandler error + expOps simtypes.OperationMsg + }{ + "error when reporter skipped": { + app: SimDeliverFn(func(_txEncoder sdk.TxEncoder, tx sdk.Tx) (sdk.GasInfo, *sdk.Result, error) { + return sdk.GasInfo{GasWanted: 100, GasUsed: 20}, &sdk.Result{}, nil + }), + reporter: func() SimulationReporter { + r := NewBasicSimulationReporter() + r.Skip("testing") + return r + }, + expOps: simtypes.NoOpMsg("", "", "testing"), + }, + "successful delivery": { + app: SimDeliverFn(func(_txEncoder sdk.TxEncoder, tx sdk.Tx) (sdk.GasInfo, *sdk.Result, error) { + return sdk.GasInfo{GasWanted: 100, GasUsed: 20}, &sdk.Result{}, nil + }), + reporter: func() SimulationReporter { return NewBasicSimulationReporter() }, + deliveryResultHandler: noopResultHandler, + expOps: simtypes.NewOperationMsgBasic("", "", "", true), + }, + "error delivery": { + app: SimDeliverFn(func(_txEncoder sdk.TxEncoder, tx sdk.Tx) (sdk.GasInfo, *sdk.Result, error) { + return sdk.GasInfo{GasWanted: 100, GasUsed: 20}, &sdk.Result{}, errors.New("my error") + }), + reporter: func() SimulationReporter { return NewBasicSimulationReporter() }, + deliveryResultHandler: noopResultHandler, + expOps: simtypes.NewOperationMsgBasic("", "", "delivering tx with msgs: &testdata.TestMsg{Signers:[]string{\"cosmos1tnh2q55v8wyygtt9srz5safamzdengsnqeycj3\"}, DecField:0.000000000000000000}", false), + }, + "error delivery handled": { + app: SimDeliverFn(func(_txEncoder sdk.TxEncoder, tx sdk.Tx) (sdk.GasInfo, *sdk.Result, error) { + return sdk.GasInfo{GasWanted: 100, GasUsed: 20}, &sdk.Result{}, errors.New("my error") + }), + reporter: func() SimulationReporter { return NewBasicSimulationReporter() }, + deliveryResultHandler: func(err error) error { return nil }, + expOps: simtypes.NewOperationMsgBasic("", "", "", true), + }, + } + for name, spec := range specs { + t.Run(name, func(t *testing.T) { + got := DeliverSimsMsg(ctx, spec.reporter(), spec.app, r, txConfig, ak, "testing", myMsg, spec.deliveryResultHandler, sender) + assert.Equal(t, spec.expOps, got) + }) + } +} diff --git a/simsx/environment.go b/simsx/environment.go new file mode 100644 index 000000000000..e5302802cce4 --- /dev/null +++ b/simsx/environment.go @@ -0,0 +1,461 @@ +package simsx + +import ( + "context" + "errors" + "math/rand" + "slices" + "time" + + "cosmossdk.io/core/address" + "cosmossdk.io/math" + + sdk "github.com/cosmos/cosmos-sdk/types" + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" +) + +// helper type for simple bank access +type contextAwareBalanceSource struct { + ctx context.Context + bank BalanceSource +} + +func (s contextAwareBalanceSource) SpendableCoins(accAddress sdk.AccAddress) sdk.Coins { + return s.bank.SpendableCoins(s.ctx, accAddress) +} + +func (s contextAwareBalanceSource) IsSendEnabledDenom(denom string) bool { + return s.bank.IsSendEnabledDenom(s.ctx, denom) +} + +// SimAccount is an extended simtypes.Account +type SimAccount struct { + simtypes.Account + r *rand.Rand + liquidBalance *SimsAccountBalance + bank contextAwareBalanceSource +} + +// LiquidBalance spendable balance. This excludes not spendable amounts like staked or vested amounts. +func (a *SimAccount) LiquidBalance() *SimsAccountBalance { + if a.liquidBalance == nil { + a.liquidBalance = NewSimsAccountBalance(a, a.r, a.bank.SpendableCoins(a.Address)) + } + return a.liquidBalance +} + +// SimsAccountBalance is a helper type for common access methods to balance amounts. +type SimsAccountBalance struct { + sdk.Coins + owner *SimAccount + r *rand.Rand +} + +// NewSimsAccountBalance constructor +func NewSimsAccountBalance(o *SimAccount, r *rand.Rand, coins sdk.Coins) *SimsAccountBalance { + return &SimsAccountBalance{Coins: coins, r: r, owner: o} +} + +type CoinsFilter interface { + Accept(c sdk.Coins) bool // returns false to reject +} +type CoinsFilterFn func(c sdk.Coins) bool + +func (f CoinsFilterFn) Accept(c sdk.Coins) bool { + return f(c) +} + +func WithSendEnabledCoins() CoinsFilter { + return statefulCoinsFilterFn(func(s *SimAccount, coins sdk.Coins) bool { + for _, coin := range coins { + if !s.bank.IsSendEnabledDenom(coin.Denom) { + return false + } + } + return true + }) +} + +// filter with context of SimAccount +type statefulCoinsFilter struct { + s *SimAccount + do func(s *SimAccount, c sdk.Coins) bool +} + +// constructor +func statefulCoinsFilterFn(f func(s *SimAccount, c sdk.Coins) bool) CoinsFilter { + return &statefulCoinsFilter{do: f} +} + +func (f statefulCoinsFilter) Accept(c sdk.Coins) bool { + if f.s == nil { + panic("account not set") + } + return f.do(f.s, c) +} + +func (f *statefulCoinsFilter) visit(s *SimAccount) { + f.s = s +} + +var _ visitable = &statefulCoinsFilter{} + +type visitable interface { + visit(s *SimAccount) +} + +// RandSubsetCoins return random amounts from the current balance. When the coins are empty, skip is called on the reporter. +// The amounts are removed from the liquid balance. +func (b *SimsAccountBalance) RandSubsetCoins(reporter SimulationReporter, filters ...CoinsFilter) sdk.Coins { + amount := b.randomAmount(5, reporter, b.Coins, filters...) + b.Coins = b.Coins.Sub(amount...) + if amount.Empty() { + reporter.Skip("got empty amounts") + } + return amount +} + +// RandSubsetCoin return random amount from the current balance. When the coins are empty, skip is called on the reporter. +// The amount is removed from the liquid balance. +func (b *SimsAccountBalance) RandSubsetCoin(reporter SimulationReporter, denom string, filters ...CoinsFilter) sdk.Coin { + ok, coin := b.Find(denom) + if !ok { + reporter.Skipf("no such coin: %s", denom) + return sdk.NewCoin(denom, math.ZeroInt()) + } + amounts := b.randomAmount(5, reporter, sdk.Coins{coin}, filters...) + if amounts.Empty() { + reporter.Skip("empty coin") + return sdk.NewCoin(denom, math.ZeroInt()) + } + b.BlockAmount(amounts[0]) + return amounts[0] +} + +// BlockAmount returns true when balance is > requested amount and subtracts the amount from the liquid balance +func (b *SimsAccountBalance) BlockAmount(amount sdk.Coin) bool { + ok, coin := b.Coins.Find(amount.Denom) + if !ok || !coin.IsPositive() || !coin.IsGTE(amount) { + return false + } + b.Coins = b.Coins.Sub(amount) + return true +} + +func (b *SimsAccountBalance) randomAmount(retryCount int, reporter SimulationReporter, coins sdk.Coins, filters ...CoinsFilter) sdk.Coins { + if retryCount < 0 || b.Coins.Empty() { + reporter.Skip("failed to find matching amount") + return sdk.Coins{} + } + amount := simtypes.RandSubsetCoins(b.r, coins) + for _, filter := range filters { + if f, ok := filter.(visitable); ok { + f.visit(b.owner) + } + if !filter.Accept(amount) { + return b.randomAmount(retryCount-1, reporter, coins, filters...) + } + } + return amount +} + +func (b *SimsAccountBalance) RandFees() sdk.Coins { + amount, err := simtypes.RandomFees(b.r, b.Coins) + if err != nil { + return sdk.Coins{} + } + return amount +} + +type SimAccountFilter interface { + // Accept returns true to accept the account or false to reject + Accept(a SimAccount) bool +} +type SimAccountFilterFn func(a SimAccount) bool + +func (s SimAccountFilterFn) Accept(a SimAccount) bool { + return s(a) +} + +func ExcludeAccounts(others ...SimAccount) SimAccountFilter { + return SimAccountFilterFn(func(a SimAccount) bool { + return !slices.ContainsFunc(others, func(o SimAccount) bool { + return a.Address.Equals(o.Address) + }) + }) +} + +// UniqueAccounts returns a stateful filter that rejects duplicate accounts. +// It uses a map to keep track of accounts that have been processed. +// If an account exists in the map, the filter function returns false +// to reject a duplicate, else it adds the account to the map and returns true. +// +// Example usage: +// +// uniqueAccountsFilter := simsx.UniqueAccounts() +// +// for { +// from := testData.AnyAccount(reporter, uniqueAccountsFilter) +// //... rest of the loop +// } +func UniqueAccounts() SimAccountFilter { + idx := make(map[string]struct{}) + return SimAccountFilterFn(func(a SimAccount) bool { + if _, ok := idx[a.AddressBech32]; ok { + return false + } + idx[a.AddressBech32] = struct{}{} + return true + }) +} + +func ExcludeAddresses(addrs ...string) SimAccountFilter { + return SimAccountFilterFn(func(a SimAccount) bool { + return !slices.Contains(addrs, a.AddressBech32) + }) +} + +func WithDenomBalance(denom string) SimAccountFilter { + return SimAccountFilterFn(func(a SimAccount) bool { + return a.LiquidBalance().AmountOf(denom).IsPositive() + }) +} + +func WithLiquidBalanceGTE(amount ...sdk.Coin) SimAccountFilter { + return SimAccountFilterFn(func(a SimAccount) bool { + return a.LiquidBalance().IsAllGTE(amount) + }) +} + +// WithSpendableBalance Filters for liquid token but send may not be enabled for all or any +func WithSpendableBalance() SimAccountFilter { + return SimAccountFilterFn(func(a SimAccount) bool { + return !a.LiquidBalance().Empty() + }) +} + +type ModuleAccountSource interface { + GetModuleAddress(moduleName string) sdk.AccAddress +} + +// BalanceSource is an interface for retrieving balance-related information for a given account. +type BalanceSource interface { + SpendableCoins(ctx context.Context, addr sdk.AccAddress) sdk.Coins + IsSendEnabledDenom(ctx context.Context, denom string) bool +} + +// ChainDataSource provides common sims test data and helper methods +type ChainDataSource struct { + r *rand.Rand + addressToAccountsPosIndex map[string]int + accounts []SimAccount + accountSource ModuleAccountSource + addressCodec address.Codec + bank contextAwareBalanceSource +} + +// NewChainDataSource constructor +func NewChainDataSource( + ctx context.Context, + r *rand.Rand, + ak ModuleAccountSource, + bk BalanceSource, + codec address.Codec, + oldSimAcc ...simtypes.Account, +) *ChainDataSource { + acc := make([]SimAccount, len(oldSimAcc)) + index := make(map[string]int, len(oldSimAcc)) + bank := contextAwareBalanceSource{ctx: ctx, bank: bk} + for i, a := range oldSimAcc { + acc[i] = SimAccount{Account: a, r: r, bank: bank} + index[a.AddressBech32] = i + if a.AddressBech32 == "" { + panic("test account has empty bech32 address") + } + } + return &ChainDataSource{ + r: r, + accountSource: ak, + addressCodec: codec, + accounts: acc, + bank: bank, + addressToAccountsPosIndex: index, + } +} + +// AnyAccount returns a random SimAccount matching the filter criteria. Module accounts are excluded. +// In case of an error or no matching account found, the reporter is set to skip and an empty value is returned. +func (c *ChainDataSource) AnyAccount(r SimulationReporter, filters ...SimAccountFilter) SimAccount { + acc := c.randomAccount(r, 5, filters...) + return acc +} + +// GetAccountbyAccAddr return SimAccount with given binary address. Reporter skip flag is set when not found. +func (c ChainDataSource) GetAccountbyAccAddr(reporter SimulationReporter, addr sdk.AccAddress) SimAccount { + if len(addr) == 0 { + reporter.Skip("can not find account for empty address") + return c.nullAccount() + } + addrStr, err := c.addressCodec.BytesToString(addr) + if err != nil { + reporter.Skipf("can not convert account address to string: %s", err) + return c.nullAccount() + } + return c.GetAccount(reporter, addrStr) +} + +func (c ChainDataSource) HasAccount(addr string) bool { + _, ok := c.addressToAccountsPosIndex[addr] + return ok +} + +// GetAccount return SimAccount with given bench32 address. Reporter skip flag is set when not found. +func (c ChainDataSource) GetAccount(reporter SimulationReporter, addr string) SimAccount { + pos, ok := c.addressToAccountsPosIndex[addr] + if !ok { + reporter.Skipf("no account: %s", addr) + return c.nullAccount() + } + return c.accounts[pos] +} + +func (c *ChainDataSource) randomAccount(reporter SimulationReporter, retryCount int, filters ...SimAccountFilter) SimAccount { + if retryCount < 0 { + reporter.Skip("failed to find a matching account") + return c.nullAccount() + } + idx := c.r.Intn(len(c.accounts)) + acc := c.accounts[idx] + for _, filter := range filters { + if !filter.Accept(acc) { + return c.randomAccount(reporter, retryCount-1, filters...) + } + } + return acc +} + +// create null object +func (c ChainDataSource) nullAccount() SimAccount { + return SimAccount{ + Account: simtypes.Account{}, + r: c.r, + liquidBalance: &SimsAccountBalance{}, + bank: c.accounts[0].bank, + } +} + +func (c *ChainDataSource) ModuleAccountAddress(reporter SimulationReporter, moduleName string) string { + acc := c.accountSource.GetModuleAddress(moduleName) + if acc == nil { + reporter.Skipf("unknown module account: %s", moduleName) + return "" + } + res, err := c.addressCodec.BytesToString(acc) + if err != nil { + reporter.Skipf("failed to encode module address: %s", err) + return "" + } + return res +} + +func (c *ChainDataSource) AddressCodec() address.Codec { + return c.addressCodec +} + +func (c *ChainDataSource) Rand() *XRand { + return &XRand{c.r} +} + +func (c *ChainDataSource) IsSendEnabledDenom(denom string) bool { + return c.bank.IsSendEnabledDenom(denom) +} + +// AllAccounts returns all accounts in legacy format +func (c *ChainDataSource) AllAccounts() []simtypes.Account { + return Collect(c.accounts, func(a SimAccount) simtypes.Account { return a.Account }) +} + +func (c *ChainDataSource) AccountsCount() int { + return len(c.accounts) +} + +// AccountAt return SimAccount within the accounts slice. Reporter skip flag is set when boundaries are exceeded. + +func (c *ChainDataSource) AccountAt(reporter SimulationReporter, i int) SimAccount { + if i > len(c.accounts) { + reporter.Skipf("account index out of range: %d", i) + return c.nullAccount() + } + return c.accounts[i] +} + +type XRand struct { + *rand.Rand +} + +// NewXRand constructor +func NewXRand(rand *rand.Rand) *XRand { + return &XRand{Rand: rand} +} + +func (r *XRand) StringN(max int) string { + return simtypes.RandStringOfLength(r.Rand, max) +} + +func (r *XRand) SubsetCoins(src sdk.Coins) sdk.Coins { + return simtypes.RandSubsetCoins(r.Rand, src) +} + +// Coin return one coin from the list +func (r *XRand) Coin(src sdk.Coins) sdk.Coin { + return src[r.Intn(len(src))] +} + +func (r *XRand) DecN(max math.LegacyDec) math.LegacyDec { + return simtypes.RandomDecAmount(r.Rand, max) +} + +func (r *XRand) IntInRange(min, max int) int { + return r.Rand.Intn(max-min) + min +} + +// Uint64InRange returns a pseudo-random uint64 number in the range [min, max]. +// It panics when min >= max +func (r *XRand) Uint64InRange(min, max uint64) uint64 { + return uint64(r.Rand.Int63n(int64(max-min)) + int64(min)) +} + +// Uint32InRange returns a pseudo-random uint32 number in the range [min, max]. +// It panics when min >= max +func (r *XRand) Uint32InRange(min, max uint32) uint32 { + return uint32(r.Rand.Intn(int(max-min))) + min +} + +func (r *XRand) PositiveSDKIntn(max math.Int) (math.Int, error) { + return simtypes.RandPositiveInt(r.Rand, max) +} + +func (r *XRand) PositiveSDKIntInRange(min, max math.Int) (math.Int, error) { + diff := max.Sub(min) + if !diff.IsPositive() { + return math.Int{}, errors.New("min value must not be greater or equal to max") + } + result, err := r.PositiveSDKIntn(diff) + if err != nil { + return math.Int{}, err + } + return result.Add(min), nil +} + +// Timestamp returns a timestamp between Jan 1, 2062 and Jan 1, 2262 +func (r *XRand) Timestamp() time.Time { + return simtypes.RandTimestamp(r.Rand) +} + +func (r *XRand) Bool() bool { + return r.Intn(100) > 50 +} + +func (r *XRand) Amount(balance math.Int) math.Int { + return simtypes.RandomAmount(r.Rand, balance) +} diff --git a/simsx/environment_test.go b/simsx/environment_test.go new file mode 100644 index 000000000000..957601326b23 --- /dev/null +++ b/simsx/environment_test.go @@ -0,0 +1,67 @@ +package simsx + +import ( + "math/rand" + "testing" + + "github.com/stretchr/testify/assert" + + sdk "github.com/cosmos/cosmos-sdk/types" + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" +) + +func TestChainDataSourceAnyAccount(t *testing.T) { + codec := txConfig().SigningContext().AddressCodec() + r := rand.New(rand.NewSource(1)) + accs := simtypes.RandomAccounts(r, 3) + specs := map[string]struct { + filters []SimAccountFilter + assert func(t *testing.T, got SimAccount, reporter SimulationReporter) + }{ + "no filters": { + assert: func(t *testing.T, got SimAccount, reporter SimulationReporter) { //nolint:thelper // not a helper + assert.NotEmpty(t, got.AddressBech32) + assert.False(t, reporter.IsSkipped()) + }, + }, + "filter": { + filters: []SimAccountFilter{SimAccountFilterFn(func(a SimAccount) bool { return a.AddressBech32 == accs[2].AddressBech32 })}, + assert: func(t *testing.T, got SimAccount, reporter SimulationReporter) { //nolint:thelper // not a helper + assert.Equal(t, accs[2].AddressBech32, got.AddressBech32) + assert.False(t, reporter.IsSkipped()) + }, + }, + "no match": { + filters: []SimAccountFilter{SimAccountFilterFn(func(a SimAccount) bool { return false })}, + assert: func(t *testing.T, got SimAccount, reporter SimulationReporter) { //nolint:thelper // not a helper + assert.Empty(t, got.AddressBech32) + assert.True(t, reporter.IsSkipped()) + }, + }, + } + for name, spec := range specs { + t.Run(name, func(t *testing.T) { + reporter := NewBasicSimulationReporter() + c := NewChainDataSource(sdk.Context{}, r, nil, nil, codec, accs...) + a := c.AnyAccount(reporter, spec.filters...) + spec.assert(t, a, reporter) + }) + } +} + +func TestChainDataSourceGetHasAccount(t *testing.T) { + codec := txConfig().SigningContext().AddressCodec() + r := rand.New(rand.NewSource(1)) + accs := simtypes.RandomAccounts(r, 3) + reporter := NewBasicSimulationReporter() + c := NewChainDataSource(sdk.Context{}, r, nil, nil, codec, accs...) + exisingAddr := accs[0].AddressBech32 + assert.Equal(t, exisingAddr, c.GetAccount(reporter, exisingAddr).AddressBech32) + assert.False(t, reporter.IsSkipped()) + assert.True(t, c.HasAccount(exisingAddr)) + // and non-existing account + reporter = NewBasicSimulationReporter() + assert.Empty(t, c.GetAccount(reporter, "non-existing").AddressBech32) + assert.False(t, c.HasAccount("non-existing")) + assert.True(t, reporter.IsSkipped()) +} diff --git a/simsx/msg_factory.go b/simsx/msg_factory.go new file mode 100644 index 000000000000..1c6b6e4b9611 --- /dev/null +++ b/simsx/msg_factory.go @@ -0,0 +1,179 @@ +package simsx + +import ( + "context" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// SimMsgFactoryX is an interface for creating and handling fuzz test-like simulation messages in the system. +type SimMsgFactoryX interface { + // MsgType returns an empty instance of the concrete message type that the factory provides. + // This instance is primarily used for deduplication and reporting purposes. + // The result must not be nil + MsgType() sdk.Msg + + // Create returns a FactoryMethod implementation which is responsible for constructing new instances of the message + // on each invocation. + Create() FactoryMethod + + // DeliveryResultHandler returns a SimDeliveryResultHandler instance which processes the delivery + // response error object. While most simulation factories anticipate successful message delivery, + // certain factories employ this handler to validate execution errors, thereby covering negative + // test scenarios. + DeliveryResultHandler() SimDeliveryResultHandler +} + +type ( + // FactoryMethod is a method signature implemented by concrete message factories for SimMsgFactoryX + // + // This factory method is responsible for creating a new `sdk.Msg` instance and determining the + // proposed signers who are expected to successfully sign the message for delivery. + // + // Parameters: + // - ctx: The context for the operation + // - testData: A pointer to a `ChainDataSource` which provides helper methods and simple access to accounts + // and balances within the chain. + // - reporter: An instance of `SimulationReporter` used to report the results of the simulation. + // If no valid message can be provided, the factory method should call `reporter.Skip("some comment")` + // with both `signer` and `msg` set to nil. + // + // Returns: + // - signer: A slice of `SimAccount` representing the proposed signers. + // - msg: An instance of `sdk.Msg` representing the message to be delivered. + FactoryMethod func(ctx context.Context, testData *ChainDataSource, reporter SimulationReporter) (signer []SimAccount, msg sdk.Msg) + + // FactoryMethodWithFutureOps extended message factory method for the gov module or others that have to schedule operations for a future block. + FactoryMethodWithFutureOps[T sdk.Msg] func(ctx context.Context, testData *ChainDataSource, reporter SimulationReporter, fOpsReg FutureOpsRegistry) ([]SimAccount, T) + + // FactoryMethodWithDeliveryResultHandler extended factory method that can return a result handler, that is executed on the delivery tx error result. + // This is used in staking for example to validate negative execution results. + FactoryMethodWithDeliveryResultHandler[T sdk.Msg] func(ctx context.Context, testData *ChainDataSource, reporter SimulationReporter) (signer []SimAccount, msg T, handler SimDeliveryResultHandler) +) + +var _ SimMsgFactoryX = &ResultHandlingSimMsgFactory[sdk.Msg]{} + +// ResultHandlingSimMsgFactory message factory with a delivery error result handler configured. +type ResultHandlingSimMsgFactory[T sdk.Msg] struct { + SimMsgFactoryFn[T] + resultHandler SimDeliveryResultHandler +} + +// NewSimMsgFactoryWithDeliveryResultHandler constructor +func NewSimMsgFactoryWithDeliveryResultHandler[T sdk.Msg](f FactoryMethodWithDeliveryResultHandler[T]) *ResultHandlingSimMsgFactory[T] { + // the result handler is always called after the factory. so we initialize it lazy for syntactic sugar and simplicity + // in the message factory function that is implemented by the users + var lazyResultHandler SimDeliveryResultHandler + r := &ResultHandlingSimMsgFactory[T]{ + resultHandler: func(err error) error { + return lazyResultHandler(err) + }, + } + r.SimMsgFactoryFn = func(ctx context.Context, testData *ChainDataSource, reporter SimulationReporter) (signer []SimAccount, msg T) { + signer, msg, lazyResultHandler = f(ctx, testData, reporter) + if lazyResultHandler == nil { + lazyResultHandler = expectNoError + } + return + } + return r +} + +func (f ResultHandlingSimMsgFactory[T]) DeliveryResultHandler() SimDeliveryResultHandler { + return f.resultHandler +} + +var ( + _ SimMsgFactoryX = &LazyStateSimMsgFactory[sdk.Msg]{} + _ HasFutureOpsRegistry = &LazyStateSimMsgFactory[sdk.Msg]{} +) + +// LazyStateSimMsgFactory stateful message factory with weighted proposals and future operation +// registry initialized lazy before execution. +type LazyStateSimMsgFactory[T sdk.Msg] struct { + SimMsgFactoryFn[T] + fsOpsReg FutureOpsRegistry +} + +func NewSimMsgFactoryWithFutureOps[T sdk.Msg](f FactoryMethodWithFutureOps[T]) *LazyStateSimMsgFactory[T] { + r := &LazyStateSimMsgFactory[T]{} + r.SimMsgFactoryFn = func(ctx context.Context, testData *ChainDataSource, reporter SimulationReporter) (signer []SimAccount, msg T) { + signer, msg = f(ctx, testData, reporter, r.fsOpsReg) + return + } + return r +} + +func (c *LazyStateSimMsgFactory[T]) SetFutureOpsRegistry(registry FutureOpsRegistry) { + c.fsOpsReg = registry +} + +// pass errors through and don't handle them +func expectNoError(err error) error { + return err +} + +var _ SimMsgFactoryX = SimMsgFactoryFn[sdk.Msg](nil) + +// SimMsgFactoryFn is the default factory for most cases. It does not create future operations but ensures successful message delivery. +type SimMsgFactoryFn[T sdk.Msg] func(ctx context.Context, testData *ChainDataSource, reporter SimulationReporter) (signer []SimAccount, msg T) + +// MsgType returns an empty instance of type T, which implements `sdk.Msg`. +func (f SimMsgFactoryFn[T]) MsgType() sdk.Msg { + var x T + return x +} + +func (f SimMsgFactoryFn[T]) Create() FactoryMethod { + // adapter to return sdk.Msg instead of typed result to match FactoryMethod signature + return func(ctx context.Context, testData *ChainDataSource, reporter SimulationReporter) ([]SimAccount, sdk.Msg) { + return f(ctx, testData, reporter) + } +} + +func (f SimMsgFactoryFn[T]) DeliveryResultHandler() SimDeliveryResultHandler { + return expectNoError +} + +func (f SimMsgFactoryFn[T]) Cast(msg sdk.Msg) T { + return msg.(T) +} + +type tuple struct { + signer []SimAccount + msg sdk.Msg +} + +// SafeRunFactoryMethod runs the factory method on a separate goroutine to abort early when the context is canceled via reporter skip +func SafeRunFactoryMethod( + ctx context.Context, + data *ChainDataSource, + reporter SimulationReporter, + f FactoryMethod, +) (signer []SimAccount, msg sdk.Msg) { + r := make(chan tuple) + go func() { + defer recoverPanicForSkipped(reporter, r) + signer, msg := f(ctx, data, reporter) + r <- tuple{signer: signer, msg: msg} + }() + select { + case t, ok := <-r: + if !ok { + return nil, nil + } + return t.signer, t.msg + case <-ctx.Done(): + reporter.Skip("context closed") + return nil, nil + } +} + +func recoverPanicForSkipped(reporter SimulationReporter, resultChan chan tuple) { + if r := recover(); r != nil { + if !reporter.IsSkipped() { + panic(r) + } + close(resultChan) + } +} diff --git a/simsx/msg_factory_test.go b/simsx/msg_factory_test.go new file mode 100644 index 000000000000..d5cadb222b69 --- /dev/null +++ b/simsx/msg_factory_test.go @@ -0,0 +1,97 @@ +package simsx + +import ( + "context" + "errors" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/cosmos/cosmos-sdk/testutil/testdata" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +func TestMsgFactories(t *testing.T) { + myMsg := testdata.NewTestMsg() + mySigners := []SimAccount{{}} + specs := map[string]struct { + src SimMsgFactoryX + expErrHandled bool + }{ + "default": { + src: SimMsgFactoryFn[*testdata.TestMsg](func(ctx context.Context, testData *ChainDataSource, reporter SimulationReporter) (signer []SimAccount, msg *testdata.TestMsg) { + return mySigners, myMsg + }), + }, + "with delivery result handler": { + src: NewSimMsgFactoryWithDeliveryResultHandler[*testdata.TestMsg](func(ctx context.Context, testData *ChainDataSource, reporter SimulationReporter) (signer []SimAccount, msg *testdata.TestMsg, handler SimDeliveryResultHandler) { + return mySigners, myMsg, func(err error) error { return nil } + }), + expErrHandled: true, + }, + "with future ops": { + src: NewSimMsgFactoryWithFutureOps[*testdata.TestMsg](func(ctx context.Context, testData *ChainDataSource, reporter SimulationReporter, fOpsReg FutureOpsRegistry) ([]SimAccount, *testdata.TestMsg) { + return mySigners, myMsg + }), + }, + } + for name, spec := range specs { + t.Run(name, func(t *testing.T) { + assert.Equal(t, (*testdata.TestMsg)(nil), spec.src.MsgType()) + + factoryMethod := spec.src.Create() + require.NotNil(t, factoryMethod) + gotSigners, gotMsg := factoryMethod(context.Background(), nil, nil) + assert.Equal(t, mySigners, gotSigners) + assert.Equal(t, gotMsg, myMsg) + + require.NotNil(t, spec.src.DeliveryResultHandler()) + gotErr := spec.src.DeliveryResultHandler()(errors.New("testing")) + assert.Equal(t, spec.expErrHandled, gotErr == nil) + }) + } +} + +func TestRunWithFailFast(t *testing.T) { + myTestMsg := testdata.NewTestMsg() + mySigners := []SimAccount{SimAccountFixture()} + specs := map[string]struct { + factory FactoryMethod + expSigners []SimAccount + expMsg sdk.Msg + expSkipped bool + }{ + "factory completes": { + factory: func(ctx context.Context, _ *ChainDataSource, reporter SimulationReporter) ([]SimAccount, sdk.Msg) { + return mySigners, myTestMsg + }, + expSigners: mySigners, + expMsg: myTestMsg, + }, + "factory skips": { + factory: func(ctx context.Context, _ *ChainDataSource, reporter SimulationReporter) ([]SimAccount, sdk.Msg) { + reporter.Skip("testing") + return nil, nil + }, + expSkipped: true, + }, + "factory skips and panics": { + factory: func(ctx context.Context, _ *ChainDataSource, reporter SimulationReporter) ([]SimAccount, sdk.Msg) { + reporter.Skip("testing") + panic("should be handled") + }, + expSkipped: true, + }, + } + for name, spec := range specs { + t.Run(name, func(t *testing.T) { + ctx, done := context.WithCancel(context.Background()) + reporter := NewBasicSimulationReporter().WithScope(&testdata.TestMsg{}, SkipHookFn(func(...any) { done() })) + gotSigners, gotMsg := SafeRunFactoryMethod(ctx, nil, reporter, spec.factory) + assert.Equal(t, spec.expSigners, gotSigners) + assert.Equal(t, spec.expMsg, gotMsg) + assert.Equal(t, spec.expSkipped, reporter.IsSkipped()) + }) + } +} diff --git a/simsx/params.go b/simsx/params.go new file mode 100644 index 000000000000..7acd6edcf84f --- /dev/null +++ b/simsx/params.go @@ -0,0 +1,52 @@ +package simsx + +import ( + "math/rand" + + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" +) + +// WeightSource interface for retrieving weights based on a name and a default value. +type WeightSource interface { + Get(name string, defaultValue uint32) uint32 +} + +// WeightSourceFn function adapter that implements WeightSource. +// Example: +// +// weightSource := WeightSourceFn(func(name string, defaultValue uint32) uint32 { +// // implementation code... +// }) +type WeightSourceFn func(name string, defaultValue uint32) uint32 + +func (f WeightSourceFn) Get(name string, defaultValue uint32) uint32 { + return f(name, defaultValue) +} + +// ParamWeightSource is an adapter to the simtypes.AppParams object. This function returns a WeightSource +// implementation that retrieves weights +// based on a name and a default value. The implementation uses the provided AppParams +// to get or generate the weight value. If the weight value exists in the AppParams, +// it is decoded and returned. Otherwise, the provided ParamSimulator is used to generate +// a random value or default value. +// +// The WeightSource implementation is a WeightSourceFn function adapter that implements +// the WeightSource interface. It takes in a name string and a defaultValue uint32 as +// parameters and returns the weight value as a uint32. +// +// Example Usage: +// +// appParams := simtypes.AppParams{} +// // add parameters to appParams +// +// weightSource := ParamWeightSource(appParams) +// weightSource.Get("some_weight", 100) +func ParamWeightSource(p simtypes.AppParams) WeightSource { + return WeightSourceFn(func(name string, defaultValue uint32) uint32 { + var result uint32 + p.GetOrGenerate("op_weight_"+name, &result, nil, func(_ *rand.Rand) { + result = defaultValue + }) + return result + }) +} diff --git a/simsx/registry.go b/simsx/registry.go new file mode 100644 index 000000000000..6aee009f379d --- /dev/null +++ b/simsx/registry.go @@ -0,0 +1,268 @@ +package simsx + +import ( + "cmp" + "context" + "iter" + "maps" + "math/rand" + "slices" + "strings" + "time" + + "cosmossdk.io/core/address" + "cosmossdk.io/core/log" + + "github.com/cosmos/cosmos-sdk/client" + sdk "github.com/cosmos/cosmos-sdk/types" + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" + "github.com/cosmos/cosmos-sdk/x/simulation" +) + +type ( + // Registry is an abstract entry point to register message factories with weights + Registry interface { + Add(weight uint32, f SimMsgFactoryX) + } + // FutureOpsRegistry register message factories for future blocks + FutureOpsRegistry interface { + Add(blockTime time.Time, f SimMsgFactoryX) + } + + // AccountSourceX Account and Module account + AccountSourceX interface { + AccountSource + ModuleAccountSource + } +) + +// WeightedProposalMsgIter iterator for weighted gov proposal payload messages +type WeightedProposalMsgIter = iter.Seq2[uint32, FactoryMethod] + +var _ Registry = &WeightedOperationRegistryAdapter{} + +// common types for abstract registry without generics +type regCommon struct { + reporter SimulationReporter + ak AccountSourceX + bk BalanceSource + addressCodec address.Codec + txConfig client.TxConfig + logger log.Logger +} + +func (c regCommon) newChainDataSource(ctx context.Context, r *rand.Rand, accs ...simtypes.Account) *ChainDataSource { + return NewChainDataSource(ctx, r, c.ak, c.bk, c.addressCodec, accs...) +} + +type AbstractRegistry[T any] struct { + regCommon + legacyObjs []T +} + +// ToLegacyObjects returns the legacy properties of the SimsRegistryAdapter as a slice of type T. +func (l *AbstractRegistry[T]) ToLegacyObjects() []T { + return l.legacyObjs +} + +// WeightedOperationRegistryAdapter is an implementation of the Registry interface that provides adapters to use the new message factories +// with the legacy simulation system +type WeightedOperationRegistryAdapter struct { + AbstractRegistry[simtypes.WeightedOperation] +} + +// NewSimsMsgRegistryAdapter creates a new instance of SimsRegistryAdapter for WeightedOperation types. +func NewSimsMsgRegistryAdapter( + reporter SimulationReporter, + ak AccountSourceX, + bk BalanceSource, + txConfig client.TxConfig, + logger log.Logger, +) *WeightedOperationRegistryAdapter { + return &WeightedOperationRegistryAdapter{ + AbstractRegistry: AbstractRegistry[simtypes.WeightedOperation]{ + regCommon: regCommon{ + reporter: reporter, + ak: ak, + bk: bk, + txConfig: txConfig, + addressCodec: txConfig.SigningContext().AddressCodec(), + logger: logger, + }, + }, + } +} + +// Add adds a new weighted operation to the collection +func (l *WeightedOperationRegistryAdapter) Add(weight uint32, fx SimMsgFactoryX) { + if fx == nil { + panic("message factory must not be nil") + } + if weight == 0 { + return + } + obj := simulation.NewWeightedOperation(int(weight), legacyOperationAdapter(l.regCommon, fx)) + l.legacyObjs = append(l.legacyObjs, obj) +} + +type HasFutureOpsRegistry interface { + SetFutureOpsRegistry(FutureOpsRegistry) +} + +// msg factory to legacy Operation type +func legacyOperationAdapter(l regCommon, fx SimMsgFactoryX) simtypes.Operation { + return func( + r *rand.Rand, app AppEntrypoint, ctx sdk.Context, + accs []simtypes.Account, chainID string, + ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { + xCtx, done := context.WithCancel(ctx) + ctx = sdk.UnwrapSDKContext(xCtx) + testData := l.newChainDataSource(ctx, r, accs...) + reporter := l.reporter.WithScope(fx.MsgType(), SkipHookFn(func(args ...any) { done() })) + fOpsReg := NewFutureOpsRegistry(l) + if fx, ok := fx.(HasFutureOpsRegistry); ok { + fx.SetFutureOpsRegistry(fOpsReg) + } + from, msg := SafeRunFactoryMethod(ctx, testData, reporter, fx.Create()) + futOps := fOpsReg.legacyObjs + weightedOpsResult := DeliverSimsMsg(ctx, reporter, app, r, l.txConfig, l.ak, chainID, msg, fx.DeliveryResultHandler(), from...) + err := reporter.Close() + return weightedOpsResult, futOps, err + } +} + +func NewFutureOpsRegistry(l regCommon) *FutureOperationRegistryAdapter { + return &FutureOperationRegistryAdapter{regCommon: l} +} + +type FutureOperationRegistryAdapter AbstractRegistry[simtypes.FutureOperation] + +func (l *FutureOperationRegistryAdapter) Add(blockTime time.Time, fx SimMsgFactoryX) { + if fx == nil { + panic("message factory must not be nil") + } + if blockTime.IsZero() { + return + } + obj := simtypes.FutureOperation{ + BlockTime: blockTime, + Op: legacyOperationAdapter(l.regCommon, fx), + } + l.legacyObjs = append(l.legacyObjs, obj) +} + +var _ Registry = &UniqueTypeRegistry{} + +type UniqueTypeRegistry map[string]WeightedFactory + +func NewUniqueTypeRegistry() UniqueTypeRegistry { + return make(UniqueTypeRegistry) +} + +func (s UniqueTypeRegistry) Add(weight uint32, f SimMsgFactoryX) { + msgType := f.MsgType() + msgTypeURL := sdk.MsgTypeURL(msgType) + if _, exists := s[msgTypeURL]; exists { + panic("type is already registered: " + msgTypeURL) + } + s[msgTypeURL] = WeightedFactory{Weight: weight, Factory: f} +} + +// Iterator returns an iterator function for a Go for loop sorted by weight desc. +func (s UniqueTypeRegistry) Iterator() WeightedProposalMsgIter { + x := maps.Values(s) + sortedWeightedFactory := slices.SortedFunc(x, func(a, b WeightedFactory) int { + return a.Compare(b) + }) + + return func(yield func(uint32, FactoryMethod) bool) { + for _, v := range sortedWeightedFactory { + if !yield(v.Weight, v.Factory.Create()) { + return + } + } + } +} + +// WeightedFactory is a Weight Factory tuple +type WeightedFactory struct { + Weight uint32 + Factory SimMsgFactoryX +} + +// Compare compares the WeightedFactory f with another WeightedFactory b. +// The comparison is done by comparing the weight of f with the weight of b. +// If the weight of f is greater than the weight of b, it returns 1. +// If the weight of f is less than the weight of b, it returns -1. +// If the weights are equal, it compares the TypeURL of the factories using strings.Compare. +// Returns an integer indicating the comparison result. +func (f WeightedFactory) Compare(b WeightedFactory) int { + switch { + case f.Weight > b.Weight: + return 1 + case f.Weight < b.Weight: + return -1 + default: + return strings.Compare(sdk.MsgTypeURL(f.Factory.MsgType()), sdk.MsgTypeURL(b.Factory.MsgType())) + } +} + +// WeightedFactoryMethod is a data tuple used for registering legacy proposal operations +type WeightedFactoryMethod struct { + Weight uint32 + Factory FactoryMethod +} + +type WeightedFactoryMethods []WeightedFactoryMethod + +// NewWeightedFactoryMethods constructor +func NewWeightedFactoryMethods() WeightedFactoryMethods { + return make(WeightedFactoryMethods, 0) +} + +// Add adds a new WeightedFactoryMethod to the WeightedFactoryMethods slice. +// If weight is zero or f is nil, it returns without making any changes. +func (s *WeightedFactoryMethods) Add(weight uint32, f FactoryMethod) { + if weight == 0 { + return + } + if f == nil { + panic("message factory must not be nil") + } + *s = append(*s, WeightedFactoryMethod{Weight: weight, Factory: f}) +} + +// Iterator returns an iterator function for a Go for loop sorted by weight desc. +func (s WeightedFactoryMethods) Iterator() WeightedProposalMsgIter { + slices.SortFunc(s, func(e, e2 WeightedFactoryMethod) int { + return cmp.Compare(e.Weight, e2.Weight) + }) + return func(yield func(uint32, FactoryMethod) bool) { + for _, v := range s { + if !yield(v.Weight, v.Factory) { + return + } + } + } +} + +// legacy operation to Msg factory type +func legacyToMsgFactoryAdapter(fn simtypes.MsgSimulatorFnX) FactoryMethod { + return func(ctx context.Context, testData *ChainDataSource, reporter SimulationReporter) (signer []SimAccount, msg sdk.Msg) { + msg, err := fn(ctx, testData.r, testData.AllAccounts(), testData.AddressCodec()) + if err != nil { + reporter.Skip(err.Error()) + return nil, nil + } + return []SimAccount{}, msg + } +} + +// AppendIterators takes multiple WeightedProposalMsgIter and returns a single iterator that sequentially yields items after each one. +func AppendIterators(iterators ...WeightedProposalMsgIter) WeightedProposalMsgIter { + return func(yield func(uint32, FactoryMethod) bool) { + for _, it := range iterators { + it(yield) + } + } +} diff --git a/simsx/registry_test.go b/simsx/registry_test.go new file mode 100644 index 000000000000..e8aba1239c7a --- /dev/null +++ b/simsx/registry_test.go @@ -0,0 +1,204 @@ +package simsx + +import ( + "context" + "errors" + "math/rand" + "testing" + "time" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "cosmossdk.io/log" + + "github.com/cosmos/cosmos-sdk/testutil/testdata" + sdk "github.com/cosmos/cosmos-sdk/types" + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" +) + +func TestSimsMsgRegistryAdapter(t *testing.T) { + senderAcc := SimAccountFixture() + accs := []simtypes.Account{senderAcc.Account} + ak := MockAccountSourceX{GetAccountFn: MemoryAccountSource(senderAcc).GetAccount} + myMsg := testdata.NewTestMsg(senderAcc.Address) + ctx := sdk.Context{}.WithContext(context.Background()) + futureTime := time.Now().Add(time.Second) + + specs := map[string]struct { + factory SimMsgFactoryX + expFactoryMsg sdk.Msg + expFactoryErr error + expDeliveryErr error + expFutureOpsCount int + }{ + "successful execution": { + factory: SimMsgFactoryFn[*testdata.TestMsg](func(ctx context.Context, testData *ChainDataSource, reporter SimulationReporter) (signer []SimAccount, msg *testdata.TestMsg) { + return []SimAccount{senderAcc}, myMsg + }), + expFactoryMsg: myMsg, + }, + "skip execution": { + factory: SimMsgFactoryFn[*testdata.TestMsg](func(ctx context.Context, testData *ChainDataSource, reporter SimulationReporter) (signer []SimAccount, msg *testdata.TestMsg) { + reporter.Skip("testing") + return nil, nil + }), + }, + "future ops registration": { + factory: NewSimMsgFactoryWithFutureOps[*testdata.TestMsg](func(ctx context.Context, testData *ChainDataSource, reporter SimulationReporter, fOpsReg FutureOpsRegistry) (signer []SimAccount, msg *testdata.TestMsg) { + fOpsReg.Add(futureTime, SimMsgFactoryFn[*testdata.TestMsg](func(ctx context.Context, testData *ChainDataSource, reporter SimulationReporter) (signer []SimAccount, msg *testdata.TestMsg) { + return []SimAccount{senderAcc}, myMsg + })) + return []SimAccount{senderAcc}, myMsg + }), + expFactoryMsg: myMsg, + expFutureOpsCount: 1, + }, + "error in factory execution": { + factory: NewSimMsgFactoryWithFutureOps[*testdata.TestMsg](func(ctx context.Context, testData *ChainDataSource, reporter SimulationReporter, fOpsReg FutureOpsRegistry) (signer []SimAccount, msg *testdata.TestMsg) { + reporter.Fail(errors.New("testing")) + return nil, nil + }), + expFactoryErr: errors.New("testing"), + }, + "missing senders": { + factory: SimMsgFactoryFn[*testdata.TestMsg](func(ctx context.Context, testData *ChainDataSource, reporter SimulationReporter) (signer []SimAccount, msg *testdata.TestMsg) { + return nil, myMsg + }), + expDeliveryErr: errors.New("no senders"), + }, + "error in delivery execution": { + factory: SimMsgFactoryFn[*testdata.TestMsg](func(ctx context.Context, testData *ChainDataSource, reporter SimulationReporter) (signer []SimAccount, msg *testdata.TestMsg) { + return []SimAccount{senderAcc}, myMsg + }), + expDeliveryErr: errors.New("testing"), + }, + } + for name, spec := range specs { + t.Run(name, func(t *testing.T) { + r := NewBasicSimulationReporter() + reg := NewSimsMsgRegistryAdapter(r, ak, nil, txConfig(), log.NewNopLogger()) + // when + reg.Add(100, spec.factory) + // then + gotOps := reg.ToLegacyObjects() + require.Len(t, gotOps, 1) + assert.Equal(t, 100, gotOps[0].Weight()) + + // and when ops executed + var capturedTXs []sdk.Tx + captureTXApp := AppEntrypointFn(func(_txEncoder sdk.TxEncoder, tx sdk.Tx) (sdk.GasInfo, *sdk.Result, error) { + capturedTXs = append(capturedTXs, tx) + return sdk.GasInfo{}, &sdk.Result{}, spec.expDeliveryErr + }) + fn := gotOps[0].Op() + gotOpsResult, gotFOps, gotErr := fn(rand.New(rand.NewSource(1)), captureTXApp, ctx, accs, "testchain") + // then + if spec.expFactoryErr != nil { + require.Equal(t, spec.expFactoryErr, gotErr) + assert.Empty(t, gotFOps) + assert.Equal(t, gotOpsResult.OK, spec.expFactoryErr == nil) + assert.Empty(t, gotOpsResult.Comment) + require.Empty(t, capturedTXs) + } + if spec.expDeliveryErr != nil { + require.Equal(t, spec.expDeliveryErr, gotErr) + } + // and verify TX delivery + if spec.expFactoryMsg != nil { + require.Len(t, capturedTXs, 1) + require.Len(t, capturedTXs[0].GetMsgs(), 1) + assert.Equal(t, spec.expFactoryMsg, capturedTXs[0].GetMsgs()[0]) + } + assert.Len(t, gotFOps, spec.expFutureOpsCount) + }) + } +} + +func TestUniqueTypeRegistry(t *testing.T) { + exampleFactory := SimMsgFactoryFn[*testdata.TestMsg](func(ctx context.Context, testData *ChainDataSource, reporter SimulationReporter) (signer []SimAccount, msg *testdata.TestMsg) { + return []SimAccount{}, nil + }) + + specs := map[string]struct { + src []WeightedFactory + exp []WeightedFactoryMethod + expErr bool + }{ + "unique": { + src: []WeightedFactory{{Weight: 1, Factory: exampleFactory}}, + exp: []WeightedFactoryMethod{{Weight: 1, Factory: exampleFactory.Create()}}, + }, + "duplicate": { + src: []WeightedFactory{{Weight: 1, Factory: exampleFactory}, {Weight: 2, Factory: exampleFactory}}, + expErr: true, + }, + } + for name, spec := range specs { + t.Run(name, func(t *testing.T) { + reg := NewUniqueTypeRegistry() + if spec.expErr { + require.Panics(t, func() { + for _, v := range spec.src { + reg.Add(v.Weight, v.Factory) + } + }) + return + } + for _, v := range spec.src { + reg.Add(v.Weight, v.Factory) + } + // then + got := readAll(reg.Iterator()) + require.Len(t, got, len(spec.exp)) + }) + } +} + +func TestWeightedFactories(t *testing.T) { + r := NewWeightedFactoryMethods() + f1 := func(ctx context.Context, testData *ChainDataSource, reporter SimulationReporter) (signer []SimAccount, msg sdk.Msg) { + panic("not implemented") + } + f2 := func(ctx context.Context, testData *ChainDataSource, reporter SimulationReporter) (signer []SimAccount, msg sdk.Msg) { + panic("not implemented") + } + r.Add(1, f1) + r.Add(2, f2) + got := readAll(r.Iterator()) + require.Len(t, got, 2) + + assert.Equal(t, uint32(1), r[0].Weight) + assert.Equal(t, uint32(2), r[1].Weight) +} + +func TestAppendIterators(t *testing.T) { + r1 := NewWeightedFactoryMethods() + r1.Add(2, func(ctx context.Context, testData *ChainDataSource, reporter SimulationReporter) (signer []SimAccount, msg sdk.Msg) { + panic("not implemented") + }) + r1.Add(2, func(ctx context.Context, testData *ChainDataSource, reporter SimulationReporter) (signer []SimAccount, msg sdk.Msg) { + panic("not implemented") + }) + r1.Add(3, func(ctx context.Context, testData *ChainDataSource, reporter SimulationReporter) (signer []SimAccount, msg sdk.Msg) { + panic("not implemented") + }) + r2 := NewUniqueTypeRegistry() + r2.Add(1, SimMsgFactoryFn[*testdata.TestMsg](func(ctx context.Context, testData *ChainDataSource, reporter SimulationReporter) (signer []SimAccount, msg *testdata.TestMsg) { + panic("not implemented") + })) + // when + all := readAll(AppendIterators(r1.Iterator(), r2.Iterator())) + // then + require.Len(t, all, 4) + gotWeights := Collect(all, func(a WeightedFactoryMethod) uint32 { return a.Weight }) + assert.Equal(t, []uint32{2, 2, 3, 1}, gotWeights) +} + +func readAll(iterator WeightedProposalMsgIter) []WeightedFactoryMethod { + var ret []WeightedFactoryMethod + for w, f := range iterator { + ret = append(ret, WeightedFactoryMethod{Weight: w, Factory: f}) + } + return ret +} diff --git a/simsx/reporter.go b/simsx/reporter.go new file mode 100644 index 000000000000..556b739518a8 --- /dev/null +++ b/simsx/reporter.go @@ -0,0 +1,260 @@ +package simsx + +import ( + "errors" + "fmt" + "maps" + "slices" + "strings" + "sync" + "sync/atomic" + + sdk "github.com/cosmos/cosmos-sdk/types" + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" +) + +// SimulationReporter is an interface for reporting the result of a simulation run. +type SimulationReporter interface { + WithScope(msg sdk.Msg, optionalSkipHook ...SkipHook) SimulationReporter + Skip(comment string) + Skipf(comment string, args ...any) + // IsSkipped returns true when skipped or completed + IsSkipped() bool + ToLegacyOperationMsg() simtypes.OperationMsg + // Fail complete with failure + Fail(err error, comments ...string) + // Success complete with success + Success(msg sdk.Msg, comments ...string) + // Close returns error captured on fail + Close() error + Comment() string +} + +var _ SimulationReporter = &BasicSimulationReporter{} + +type ReporterStatus uint8 + +const ( + undefined ReporterStatus = iota + skipped ReporterStatus = iota + completed ReporterStatus = iota +) + +func (s ReporterStatus) String() string { + switch s { + case skipped: + return "skipped" + case completed: + return "completed" + default: + return "undefined" + } +} + +// SkipHook is an interface that represents a callback hook used triggered on skip operations. +// It provides a single method `Skip` that accepts variadic arguments. This interface is implemented +// by Go stdlib testing.T and testing.B +type SkipHook interface { + Skip(args ...any) +} + +var _ SkipHook = SkipHookFn(nil) + +type SkipHookFn func(args ...any) + +func (s SkipHookFn) Skip(args ...any) { + s(args...) +} + +type BasicSimulationReporter struct { + skipCallbacks []SkipHook + completedCallback func(reporter *BasicSimulationReporter) + module string + msgTypeURL string + + status atomic.Uint32 + + cMX sync.RWMutex + comments []string + error error + + summary *ExecutionSummary +} + +// NewBasicSimulationReporter constructor that accepts an optional callback hook that is called on state transition to skipped status +// A typical implementation for this hook is testing.T or testing.B. +func NewBasicSimulationReporter(optionalSkipHook ...SkipHook) *BasicSimulationReporter { + r := &BasicSimulationReporter{ + skipCallbacks: optionalSkipHook, + summary: NewExecutionSummary(), + } + r.completedCallback = func(child *BasicSimulationReporter) { + r.summary.Add(child.module, child.msgTypeURL, ReporterStatus(child.status.Load()), child.Comment()) + } + return r +} + +// WithScope is a method of the BasicSimulationReporter type that creates a new instance of SimulationReporter +// with an additional scope specified by the input `msg`. The msg is used to set type, module and binary data as +// context for the legacy operation. +// The WithScope method acts as a constructor to initialize state and has to be called before using the instance +// in DeliverSimsMsg. +// +// The method accepts an optional `optionalSkipHook` parameter +// that can be used to add a callback hook that is triggered on skip operations additional to any parent skip hook. +// This method returns the newly created +// SimulationReporter instance. +func (x *BasicSimulationReporter) WithScope(msg sdk.Msg, optionalSkipHook ...SkipHook) SimulationReporter { + typeURL := sdk.MsgTypeURL(msg) + r := &BasicSimulationReporter{ + skipCallbacks: append(x.skipCallbacks, optionalSkipHook...), + completedCallback: x.completedCallback, + error: x.error, + msgTypeURL: typeURL, + module: sdk.GetModuleNameFromTypeURL(typeURL), + comments: slices.Clone(x.comments), + } + r.status.Store(x.status.Load()) + return r +} + +func (x *BasicSimulationReporter) Skip(comment string) { + x.toStatus(skipped, comment) +} + +func (x *BasicSimulationReporter) Skipf(comment string, args ...any) { + x.Skip(fmt.Sprintf(comment, args...)) +} + +func (x *BasicSimulationReporter) IsSkipped() bool { + return ReporterStatus(x.status.Load()) > undefined +} + +func (x *BasicSimulationReporter) ToLegacyOperationMsg() simtypes.OperationMsg { + switch ReporterStatus(x.status.Load()) { + case skipped: + return simtypes.NoOpMsg(x.module, x.msgTypeURL, x.Comment()) + case completed: + x.cMX.RLock() + err := x.error + x.cMX.RUnlock() + if err == nil { + return simtypes.NewOperationMsgBasic(x.module, x.msgTypeURL, x.Comment(), true) + } else { + return simtypes.NewOperationMsgBasic(x.module, x.msgTypeURL, x.Comment(), false) + } + default: + x.Fail(errors.New("operation aborted before msg was executed")) + return x.ToLegacyOperationMsg() + } +} + +func (x *BasicSimulationReporter) Fail(err error, comments ...string) { + if !x.toStatus(completed, comments...) { + return + } + x.cMX.Lock() + defer x.cMX.Unlock() + x.error = err +} + +func (x *BasicSimulationReporter) Success(msg sdk.Msg, comments ...string) { + if !x.toStatus(completed, comments...) { + return + } + if msg == nil { + return + } +} + +func (x *BasicSimulationReporter) Close() error { + x.completedCallback(x) + x.cMX.RLock() + defer x.cMX.RUnlock() + return x.error +} + +func (x *BasicSimulationReporter) toStatus(next ReporterStatus, comments ...string) bool { + oldStatus := ReporterStatus(x.status.Load()) + if oldStatus > next { + panic(fmt.Sprintf("can not switch from status %s to %s", oldStatus, next)) + } + if !x.status.CompareAndSwap(uint32(oldStatus), uint32(next)) { + return false + } + x.cMX.Lock() + newComments := append(x.comments, comments...) + x.comments = newComments + x.cMX.Unlock() + + if oldStatus != skipped && next == skipped { + prettyComments := strings.Join(newComments, ", ") + for _, hook := range x.skipCallbacks { + hook.Skip(prettyComments) + } + } + return true +} + +func (x *BasicSimulationReporter) Comment() string { + x.cMX.RLock() + defer x.cMX.RUnlock() + return strings.Join(x.comments, ", ") +} + +func (x *BasicSimulationReporter) Summary() *ExecutionSummary { + return x.summary +} + +type ExecutionSummary struct { + mx sync.RWMutex + counts map[string]int // module to count + skipReasons map[string]map[string]int // msg type to reason->count +} + +func NewExecutionSummary() *ExecutionSummary { + return &ExecutionSummary{counts: make(map[string]int), skipReasons: make(map[string]map[string]int)} +} + +func (s *ExecutionSummary) Add(module, url string, status ReporterStatus, comment string) { + s.mx.Lock() + defer s.mx.Unlock() + combinedKey := fmt.Sprintf("%s_%s", module, status.String()) + s.counts[combinedKey] += 1 + if status == completed { + return + } + r, ok := s.skipReasons[url] + if !ok { + r = make(map[string]int) + s.skipReasons[url] = r + } + r[comment] += 1 +} + +func (s *ExecutionSummary) String() string { + s.mx.RLock() + defer s.mx.RUnlock() + keys := slices.Sorted(maps.Keys(s.counts)) + var sb strings.Builder + for _, key := range keys { + sb.WriteString(fmt.Sprintf("%s: %d\n", key, s.counts[key])) + } + if len(s.skipReasons) != 0 { + sb.WriteString("\nSkip reasons:\n") + } + for m, c := range s.skipReasons { + values := maps.Values(c) + keys := maps.Keys(c) + sb.WriteString(fmt.Sprintf("%d\t%s: %q\n", sum(slices.Collect(values)), m, slices.Collect(keys))) + } + return sb.String() +} + +func sum(values []int) int { + var r int + for _, v := range values { + r += v + } + return r +} diff --git a/simsx/reporter_test.go b/simsx/reporter_test.go new file mode 100644 index 000000000000..2bc47fe902b0 --- /dev/null +++ b/simsx/reporter_test.go @@ -0,0 +1,219 @@ +package simsx + +import ( + "errors" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/cosmos/cosmos-sdk/testutil/testdata" + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" +) + +func TestSimulationReporterToLegacy(t *testing.T) { + myErr := errors.New("my-error") + myMsg := testdata.NewTestMsg([]byte{1}) + + specs := map[string]struct { + setup func() SimulationReporter + expOp simtypes.OperationMsg + expErr error + }{ + "init only": { + setup: func() SimulationReporter { return NewBasicSimulationReporter() }, + expOp: simtypes.NewOperationMsgBasic("", "", "", false), + expErr: errors.New("operation aborted before msg was executed"), + }, + "success result": { + setup: func() SimulationReporter { + r := NewBasicSimulationReporter().WithScope(myMsg) + r.Success(myMsg, "testing") + return r + }, + expOp: simtypes.NewOperationMsgBasic("TestMsg", "/testpb.TestMsg", "testing", true), + }, + "error result": { + setup: func() SimulationReporter { + r := NewBasicSimulationReporter().WithScope(myMsg) + r.Fail(myErr, "testing") + return r + }, + expOp: simtypes.NewOperationMsgBasic("TestMsg", "/testpb.TestMsg", "testing", false), + expErr: myErr, + }, + "last error wins": { + setup: func() SimulationReporter { + r := NewBasicSimulationReporter().WithScope(myMsg) + r.Fail(errors.New("other-err"), "testing1") + r.Fail(myErr, "testing2") + return r + }, + expOp: simtypes.NewOperationMsgBasic("TestMsg", "/testpb.TestMsg", "testing1, testing2", false), + expErr: myErr, + }, + "skipped ": { + setup: func() SimulationReporter { + r := NewBasicSimulationReporter().WithScope(myMsg) + r.Skip("testing") + return r + }, + expOp: simtypes.NoOpMsg("TestMsg", "/testpb.TestMsg", "testing"), + }, + } + for name, spec := range specs { + t.Run(name, func(t *testing.T) { + r := spec.setup() + assert.Equal(t, spec.expOp, r.ToLegacyOperationMsg()) + require.Equal(t, spec.expErr, r.Close()) + }) + } +} + +func TestSimulationReporterTransitions(t *testing.T) { + specs := map[string]struct { + setup func(r SimulationReporter) + expStatus ReporterStatus + expPanic bool + }{ + "undefined->skipped": { + setup: func(r SimulationReporter) { + r.Skip("testing") + }, + expStatus: skipped, + }, + "skipped->skipped": { + setup: func(r SimulationReporter) { + r.Skip("testing1") + r.Skip("testing2") + }, + expStatus: skipped, + }, + "skipped->completed": { + setup: func(r SimulationReporter) { + r.Skip("testing1") + r.Success(nil, "testing2") + }, + expStatus: completed, + }, + "completed->completed": { + setup: func(r SimulationReporter) { + r.Success(nil, "testing1") + r.Fail(nil, "testing2") + }, + expStatus: completed, + }, + "completed->completed2": { + setup: func(r SimulationReporter) { + r.Fail(nil, "testing1") + r.Success(nil, "testing2") + }, + expStatus: completed, + }, + "completed->skipped: rejected": { + setup: func(r SimulationReporter) { + r.Success(nil, "testing1") + r.Skip("testing2") + }, + expPanic: true, + }, + } + for name, spec := range specs { + t.Run(name, func(t *testing.T) { + r := NewBasicSimulationReporter() + if !spec.expPanic { + spec.setup(r) + assert.Equal(t, uint32(spec.expStatus), r.status.Load()) + return + } + require.Panics(t, func() { + spec.setup(r) + }) + }) + } +} + +func TestSkipHook(t *testing.T) { + myHook := func() (SkipHookFn, *bool) { + var hookCalled bool + return func(args ...any) { + hookCalled = true + }, &hookCalled + } + fn, myHookCalled := myHook() + r := NewBasicSimulationReporter(fn) + r.Skip("testing") + require.True(t, *myHookCalled) + + // and with nested reporter + fn, myHookCalled = myHook() + r = NewBasicSimulationReporter(fn) + fn2, myOtherHookCalled := myHook() + r2 := r.WithScope(testdata.NewTestMsg([]byte{1}), fn2) + r2.Skipf("testing %d", 2) + assert.True(t, *myHookCalled) + assert.True(t, *myOtherHookCalled) +} + +func TestReporterSummary(t *testing.T) { + specs := map[string]struct { + do func(t *testing.T, r SimulationReporter) + expSummary map[string]int + expReasons map[string]map[string]int + }{ + "skipped": { + do: func(t *testing.T, r SimulationReporter) { //nolint:thelper // not a helper + r2 := r.WithScope(testdata.NewTestMsg([]byte{1})) + r2.Skip("testing") + require.NoError(t, r2.Close()) + }, + expSummary: map[string]int{"TestMsg_skipped": 1}, + expReasons: map[string]map[string]int{"/testpb.TestMsg": {"testing": 1}}, + }, + "success result": { + do: func(t *testing.T, r SimulationReporter) { //nolint:thelper // not a helper + msg := testdata.NewTestMsg([]byte{1}) + r2 := r.WithScope(msg) + r2.Success(msg) + require.NoError(t, r2.Close()) + }, + expSummary: map[string]int{"TestMsg_completed": 1}, + expReasons: map[string]map[string]int{}, + }, + "error result": { + do: func(t *testing.T, r SimulationReporter) { //nolint:thelper // not a helper + msg := testdata.NewTestMsg([]byte{1}) + r2 := r.WithScope(msg) + r2.Fail(errors.New("testing")) + require.Error(t, r2.Close()) + }, + expSummary: map[string]int{"TestMsg_completed": 1}, + expReasons: map[string]map[string]int{}, + }, + "multiple skipped": { + do: func(t *testing.T, r SimulationReporter) { //nolint:thelper // not a helper + r2 := r.WithScope(testdata.NewTestMsg([]byte{1})) + r2.Skip("testing1") + require.NoError(t, r2.Close()) + r3 := r.WithScope(testdata.NewTestMsg([]byte{2})) + r3.Skip("testing2") + require.NoError(t, r3.Close()) + }, + expSummary: map[string]int{"TestMsg_skipped": 2}, + expReasons: map[string]map[string]int{ + "/testpb.TestMsg": {"testing1": 1, "testing2": 1}, + }, + }, + } + for name, spec := range specs { + t.Run(name, func(t *testing.T) { + r := NewBasicSimulationReporter() + // when + spec.do(t, r) + gotSummary := r.Summary() + // then + require.Equal(t, spec.expSummary, gotSummary.counts) + require.Equal(t, spec.expReasons, gotSummary.skipReasons) + }) + } +} diff --git a/simsx/runner.go b/simsx/runner.go new file mode 100644 index 000000000000..291f517a7448 --- /dev/null +++ b/simsx/runner.go @@ -0,0 +1,372 @@ +package simsx + +import ( + "encoding/json" + "fmt" + "io" + "os" + "path/filepath" + "testing" + + dbm "github.com/cosmos/cosmos-db" + "github.com/stretchr/testify/require" + + corestore "cosmossdk.io/core/store" + "cosmossdk.io/log" + + "github.com/cosmos/cosmos-sdk/baseapp" + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/runtime" + "github.com/cosmos/cosmos-sdk/server" + servertypes "github.com/cosmos/cosmos-sdk/server/types" + simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/module" + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" + "github.com/cosmos/cosmos-sdk/x/simulation" + "github.com/cosmos/cosmos-sdk/x/simulation/client/cli" +) + +const SimAppChainID = "simulation-app" + +// this list of seeds was imported from the original simulation runner: https://github.com/cosmos/tools/blob/v1.0.0/cmd/runsim/main.go#L32 +var defaultSeeds = []int64{ + 1, 2, 4, 7, + 32, 123, 124, 582, 1893, 2989, + 3012, 4728, 37827, 981928, 87821, 891823782, + 989182, 89182391, 11, 22, 44, 77, 99, 2020, + 3232, 123123, 124124, 582582, 18931893, + 29892989, 30123012, 47284728, 7601778, 8090485, + 977367484, 491163361, 424254581, 673398983, +} + +// SimStateFactory is a factory type that provides a convenient way to create a simulation state for testing. +// It contains the following fields: +// - Codec: a codec used for serializing other objects +// - AppStateFn: a function that returns the app state JSON bytes and the genesis accounts +// - BlockedAddr: a map of blocked addresses +// - AccountSource: an interface for retrieving accounts +// - BalanceSource: an interface for retrieving balance-related information +type SimStateFactory struct { + Codec codec.Codec + AppStateFn simtypes.AppStateFn + BlockedAddr map[string]bool + AccountSource AccountSourceX + BalanceSource BalanceSource +} + +// SimulationApp abstract app that is used by sims +type SimulationApp interface { + runtime.AppSimI + SetNotSigverifyTx() + GetBaseApp() *baseapp.BaseApp + TxConfig() client.TxConfig + Close() error +} + +// Run is a helper function that runs a simulation test with the given parameters. +// It calls the RunWithSeeds function with the default seeds and parameters. +// +// This is the entrypoint to run simulation tests that used to run with the runsim binary. +func Run[T SimulationApp]( + t *testing.T, + appFactory func( + logger log.Logger, + db corestore.KVStoreWithBatch, + traceStore io.Writer, + loadLatest bool, + appOpts servertypes.AppOptions, + baseAppOptions ...func(*baseapp.BaseApp), + ) T, + setupStateFactory func(app T) SimStateFactory, + postRunActions ...func(t testing.TB, app TestInstance[T], accs []simtypes.Account), +) { + t.Helper() + RunWithSeeds(t, appFactory, setupStateFactory, defaultSeeds, nil, postRunActions...) +} + +// RunWithSeeds is a helper function that runs a simulation test with the given parameters. +// It iterates over the provided seeds and runs the simulation test for each seed in parallel. +// +// It sets up the environment, creates an instance of the simulation app, +// calls the simulation.SimulateFromSeed function to run the simulation, and performs post-run actions for each seed. +// The execution is deterministic and can be used for fuzz tests as well. +// +// The system under test is isolated for each run but unlike the old runsim command, there is no Process separation. +// This means, global caches may be reused for example. This implementation build upon the vanilla Go stdlib test framework. +func RunWithSeeds[T SimulationApp]( + t *testing.T, + appFactory func( + logger log.Logger, + db corestore.KVStoreWithBatch, + traceStore io.Writer, + loadLatest bool, + appOpts servertypes.AppOptions, + baseAppOptions ...func(*baseapp.BaseApp), + ) T, + setupStateFactory func(app T) SimStateFactory, + seeds []int64, + fuzzSeed []byte, + postRunActions ...func(t testing.TB, app TestInstance[T], accs []simtypes.Account), +) { + t.Helper() + cfg := cli.NewConfigFromFlags() + cfg.ChainID = SimAppChainID + for i := range seeds { + seed := seeds[i] + t.Run(fmt.Sprintf("seed: %d", seed), func(t *testing.T) { + t.Parallel() + RunWithSeed(t, cfg, appFactory, setupStateFactory, seed, fuzzSeed, postRunActions...) + }) + } +} + +// RunWithSeed is a helper function that runs a simulation test with the given parameters. +// It iterates over the provided seeds and runs the simulation test for each seed in parallel. +// +// It sets up the environment, creates an instance of the simulation app, +// calls the simulation.SimulateFromSeed function to run the simulation, and performs post-run actions for the seed. +// The execution is deterministic and can be used for fuzz tests as well. +func RunWithSeed[T SimulationApp]( + tb testing.TB, + cfg simtypes.Config, + appFactory func(logger log.Logger, db corestore.KVStoreWithBatch, traceStore io.Writer, loadLatest bool, appOpts servertypes.AppOptions, baseAppOptions ...func(*baseapp.BaseApp)) T, + setupStateFactory func(app T) SimStateFactory, + seed int64, + fuzzSeed []byte, + postRunActions ...func(t testing.TB, app TestInstance[T], accs []simtypes.Account), +) { + tb.Helper() + // setup environment + tCfg := cfg.With(tb, seed, fuzzSeed) + testInstance := NewSimulationAppInstance(tb, tCfg, appFactory) + var runLogger log.Logger + if cli.FlagVerboseValue { + runLogger = log.NewTestLogger(tb) + } else { + runLogger = log.NewTestLoggerInfo(tb) + } + runLogger = runLogger.With("seed", tCfg.Seed) + + app := testInstance.App + stateFactory := setupStateFactory(app) + ops, reporter := prepareWeightedOps(app.SimulationManager(), stateFactory, tCfg, testInstance.App.TxConfig(), runLogger) + simParams, accs, err := simulation.SimulateFromSeedX(tb, runLogger, WriteToDebugLog(runLogger), app.GetBaseApp(), stateFactory.AppStateFn, simtypes.RandomAccounts, ops, stateFactory.BlockedAddr, tCfg, stateFactory.Codec, testInstance.ExecLogWriter) + require.NoError(tb, err) + err = simtestutil.CheckExportSimulation(app, tCfg, simParams) + require.NoError(tb, err) + if tCfg.Commit && tCfg.DBBackend == "goleveldb" { + simtestutil.PrintStats(testInstance.DB.(*dbm.GoLevelDB), tb.Log) + } + // not using tb.Log to always print the summary + fmt.Printf("+++ DONE (seed: %d): \n%s\n", seed, reporter.Summary().String()) + for _, step := range postRunActions { + step(tb, testInstance, accs) + } + require.NoError(tb, app.Close()) +} + +type ( + HasWeightedOperationsX interface { + WeightedOperationsX(weight WeightSource, reg Registry) + } + HasWeightedOperationsXWithProposals interface { + WeightedOperationsX(weights WeightSource, reg Registry, proposals WeightedProposalMsgIter, + legacyProposals []simtypes.WeightedProposalContent) //nolint: staticcheck // used for legacy proposal types + } + HasProposalMsgsX interface { + ProposalMsgsX(weights WeightSource, reg Registry) + } +) + +type ( + HasLegacyWeightedOperations interface { + // WeightedOperations simulation operations (i.e msgs) with their respective weight + WeightedOperations(simState module.SimulationState) []simtypes.WeightedOperation + } + // HasLegacyProposalMsgs defines the messages that can be used to simulate governance (v1) proposals + // Deprecated replaced by HasProposalMsgsX + HasLegacyProposalMsgs interface { + // ProposalMsgs msg fu nctions used to simulate governance proposals + ProposalMsgs(simState module.SimulationState) []simtypes.WeightedProposalMsg + } + + // HasLegacyProposalContents defines the contents that can be used to simulate legacy governance (v1beta1) proposals + // Deprecated replaced by HasProposalMsgsX + HasLegacyProposalContents interface { + // ProposalContents content functions used to simulate governance proposals + ProposalContents(simState module.SimulationState) []simtypes.WeightedProposalContent //nolint:staticcheck // legacy v1beta1 governance + } +) + +// TestInstance is a generic type that represents an instance of a SimulationApp used for testing simulations. +// It contains the following fields: +// - App: The instance of the SimulationApp under test. +// - DB: The LevelDB database for the simulation app. +// - WorkDir: The temporary working directory for the simulation app. +// - Cfg: The configuration flags for the simulator. +// - AppLogger: The logger used for logging in the app during the simulation, with seed value attached. +// - ExecLogWriter: Captures block and operation data coming from the simulation +type TestInstance[T SimulationApp] struct { + App T + DB corestore.KVStoreWithBatch + WorkDir string + Cfg simtypes.Config + AppLogger log.Logger + ExecLogWriter simulation.LogWriter +} + +// included to avoid cyclic dependency in testutils/sims +func prepareWeightedOps( + sm *module.SimulationManager, + stateFact SimStateFactory, + config simtypes.Config, + txConfig client.TxConfig, + logger log.Logger, +) (simulation.WeightedOperations, *BasicSimulationReporter) { + cdc := stateFact.Codec + signingCtx := cdc.InterfaceRegistry().SigningContext() + simState := module.SimulationState{ + AppParams: make(simtypes.AppParams), + Cdc: cdc, + AddressCodec: signingCtx.AddressCodec(), + ValidatorCodec: signingCtx.ValidatorAddressCodec(), + TxConfig: txConfig, + BondDenom: sdk.DefaultBondDenom, + } + + if config.ParamsFile != "" { + bz, err := os.ReadFile(config.ParamsFile) + if err != nil { + panic(err) + } + + err = json.Unmarshal(bz, &simState.AppParams) + if err != nil { + panic(err) + } + } + + weights := ParamWeightSource(simState.AppParams) + reporter := NewBasicSimulationReporter() + + pReg := make(UniqueTypeRegistry) + wContent := make([]simtypes.WeightedProposalContent, 0) //nolint:staticcheck // required for legacy type + legacyPReg := NewWeightedFactoryMethods() + // add gov proposals types + for _, m := range sm.Modules { + switch xm := m.(type) { + case HasProposalMsgsX: + xm.ProposalMsgsX(weights, pReg) + case HasLegacyProposalMsgs: + for _, p := range xm.ProposalMsgs(simState) { + weight := weights.Get(p.AppParamsKey(), uint32(p.DefaultWeight())) + legacyPReg.Add(weight, legacyToMsgFactoryAdapter(p.MsgSimulatorFn())) + } + case HasLegacyProposalContents: + wContent = append(wContent, xm.ProposalContents(simState)...) + } + } + + oReg := NewSimsMsgRegistryAdapter(reporter, stateFact.AccountSource, stateFact.BalanceSource, txConfig, logger) + wOps := make([]simtypes.WeightedOperation, 0, len(sm.Modules)) + for _, m := range sm.Modules { + // add operations + switch xm := m.(type) { + case HasWeightedOperationsX: + xm.WeightedOperationsX(weights, oReg) + case HasWeightedOperationsXWithProposals: + xm.WeightedOperationsX(weights, oReg, AppendIterators(legacyPReg.Iterator(), pReg.Iterator()), wContent) + case HasLegacyWeightedOperations: + wOps = append(wOps, xm.WeightedOperations(simState)...) + } + } + return append(wOps, oReg.ToLegacyObjects()...), reporter +} + +// NewSimulationAppInstance initializes and returns a TestInstance of a SimulationApp. +// The function takes a testing.T instance, a simtypes.Config instance, and an appFactory function as parameters. +// It creates a temporary working directory and a LevelDB database for the simulation app. +// The function then initializes a logger based on the verbosity flag and sets the logger's seed to the test configuration's seed. +// The database is closed and cleaned up on test completion. +func NewSimulationAppInstance[T SimulationApp]( + tb testing.TB, + tCfg simtypes.Config, + appFactory func(logger log.Logger, db corestore.KVStoreWithBatch, traceStore io.Writer, loadLatest bool, appOpts servertypes.AppOptions, baseAppOptions ...func(*baseapp.BaseApp)) T, +) TestInstance[T] { + tb.Helper() + workDir := tb.TempDir() + require.NoError(tb, os.Mkdir(filepath.Join(workDir, "data"), 0o755)) + dbDir := filepath.Join(workDir, "leveldb-app-sim") + var logger log.Logger + if cli.FlagVerboseValue { + logger = log.NewTestLogger(tb) + } else { + logger = log.NewTestLoggerError(tb) + } + logger = logger.With("seed", tCfg.Seed) + db, err := dbm.NewDB("Simulation", dbm.BackendType(tCfg.DBBackend), dbDir) + require.NoError(tb, err) + tb.Cleanup(func() { + _ = db.Close() // ensure db is closed + }) + appOptions := make(simtestutil.AppOptionsMap) + appOptions[flags.FlagHome] = workDir + appOptions[server.FlagInvCheckPeriod] = cli.FlagPeriodValue + opts := []func(*baseapp.BaseApp){baseapp.SetChainID(SimAppChainID)} + if tCfg.FauxMerkle { + opts = append(opts, FauxMerkleModeOpt) + } + app := appFactory(logger, db, nil, true, appOptions, opts...) + if !cli.FlagSigverifyTxValue { + app.SetNotSigverifyTx() + } + return TestInstance[T]{ + App: app, + DB: db, + WorkDir: workDir, + Cfg: tCfg, + AppLogger: logger, + ExecLogWriter: &simulation.StandardLogWriter{Seed: tCfg.Seed}, + } +} + +var _ io.Writer = writerFn(nil) + +type writerFn func(p []byte) (n int, err error) + +func (w writerFn) Write(p []byte) (n int, err error) { + return w(p) +} + +// WriteToDebugLog is an adapter to io.Writer interface +func WriteToDebugLog(logger log.Logger) io.Writer { + return writerFn(func(p []byte) (n int, err error) { + logger.Debug(string(p)) + return len(p), nil + }) +} + +// AppOptionsFn is an adapter to the single method AppOptions interface +type AppOptionsFn func(string) any + +func (f AppOptionsFn) Get(k string) any { + return f(k) +} + +func (f AppOptionsFn) GetString(k string) string { + str, ok := f(k).(string) + if !ok { + return "" + } + + return str +} + +// FauxMerkleModeOpt returns a BaseApp option to use a dbStoreAdapter instead of +// an IAVLStore for faster simulation speed. +func FauxMerkleModeOpt(bapp *baseapp.BaseApp) { + bapp.SetFauxMerkleMode() +} diff --git a/simsx/slices.go b/simsx/slices.go new file mode 100644 index 000000000000..3466cd6f971c --- /dev/null +++ b/simsx/slices.go @@ -0,0 +1,38 @@ +package simsx + +// Collect applies the function f to each element in the source slice, +// returning a new slice containing the results. +// +// The source slice can contain elements of any type T, and the function f +// should take an element of type T as input and return a value of any type E. +// +// Example usage: +// +// source := []int{1, 2, 3, 4, 5} +// double := Collect(source, func(x int) int { +// return x * 2 +// }) +// // double is now []int{2, 4, 6, 8, 10} +func Collect[T, E any](source []T, f func(a T) E) []E { + r := make([]E, len(source)) + for i, v := range source { + r[i] = f(v) + } + return r +} + +// First returns the first element in the slice that matches the condition +func First[T any](source []T, f func(a T) bool) *T { + for i := 0; i < len(source); i++ { + if f(source[i]) { + return &source[i] + } + } + return nil +} + +// OneOf returns a random element from the given slice using the provided random number generator. +// Panics for empty or nil slice +func OneOf[T any](r interface{ Intn(n int) int }, s []T) T { + return s[r.Intn(len(s))] +} diff --git a/simsx/slices_test.go b/simsx/slices_test.go new file mode 100644 index 000000000000..40decc173bd2 --- /dev/null +++ b/simsx/slices_test.go @@ -0,0 +1,40 @@ +package simsx + +import ( + "strconv" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestCollect(t *testing.T) { + src := []int{1, 2, 3} + got := Collect(src, func(a int) int { return a * 2 }) + assert.Equal(t, []int{2, 4, 6}, got) + gotStrings := Collect(src, strconv.Itoa) + assert.Equal(t, []string{"1", "2", "3"}, gotStrings) +} + +func TestFirst(t *testing.T) { + src := []string{"a", "b"} + assert.Equal(t, &src[1], First(src, func(a string) bool { return a == "b" })) + assert.Nil(t, First(src, func(a string) bool { return false })) +} + +func TestOneOf(t *testing.T) { + src := []string{"a", "b"} + got := OneOf(randMock{next: 1}, src) + assert.Equal(t, "b", got) + // test with other type + src2 := []int{1, 2, 3} + got2 := OneOf(randMock{next: 2}, src2) + assert.Equal(t, 3, got2) +} + +type randMock struct { + next int +} + +func (x randMock) Intn(n int) int { + return x.next +} diff --git a/store/cachekv/search_test.go b/store/cachekv/search_test.go index 41321c076eae..aedc0669030a 100644 --- a/store/cachekv/search_test.go +++ b/store/cachekv/search_test.go @@ -60,7 +60,6 @@ func TestFindStartIndex(t *testing.T) { } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { body := tt.sortedL got := findStartIndex(body, tt.query) @@ -129,7 +128,6 @@ func TestFindEndIndex(t *testing.T) { } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { body := tt.sortedL got := findEndIndex(body, tt.query) diff --git a/store/cachekv/store.go b/store/cachekv/store.go index bce28e4b2d3f..3509cef6aee3 100644 --- a/store/cachekv/store.go +++ b/store/cachekv/store.go @@ -300,7 +300,7 @@ func (store *Store) dirtyItems(start, end []byte) { } n := len(store.unsortedCache) - unsorted := make([]*kv.Pair, 0) + unsorted := make([]*kv.Pair, 0) //nolint:staticcheck // We are in store v1. // If the unsortedCache is too big, its costs too much to determine // what's in the subset we are concerned about. // If you are interleaving iterator calls with writes, this can easily become an @@ -312,7 +312,7 @@ func (store *Store) dirtyItems(start, end []byte) { // dbm.IsKeyInDomain is nil safe and returns true iff key is greater than start if dbm.IsKeyInDomain(conv.UnsafeStrToBytes(key), start, end) { cacheValue := store.cache[key] - unsorted = append(unsorted, &kv.Pair{Key: []byte(key), Value: cacheValue.value}) + unsorted = append(unsorted, &kv.Pair{Key: []byte(key), Value: cacheValue.value}) //nolint:staticcheck // We are in store v1. } } store.clearUnsortedCacheSubset(unsorted, stateUnsorted) @@ -355,18 +355,18 @@ func (store *Store) dirtyItems(start, end []byte) { } } - kvL := make([]*kv.Pair, 0, 1+endIndex-startIndex) + kvL := make([]*kv.Pair, 0, 1+endIndex-startIndex) //nolint:staticcheck // We are in store v1. for i := startIndex; i <= endIndex; i++ { key := strL[i] cacheValue := store.cache[key] - kvL = append(kvL, &kv.Pair{Key: []byte(key), Value: cacheValue.value}) + kvL = append(kvL, &kv.Pair{Key: []byte(key), Value: cacheValue.value}) //nolint:staticcheck // We are in store v1. } // kvL was already sorted so pass it in as is. store.clearUnsortedCacheSubset(kvL, stateAlreadySorted) } -func (store *Store) clearUnsortedCacheSubset(unsorted []*kv.Pair, sortState sortState) { +func (store *Store) clearUnsortedCacheSubset(unsorted []*kv.Pair, sortState sortState) { //nolint:staticcheck // We are in store v1. n := len(store.unsortedCache) if len(unsorted) == n { // This pattern allows the Go compiler to emit the map clearing idiom for the entire map. for key := range store.unsortedCache { diff --git a/store/cachekv/store_test.go b/store/cachekv/store_test.go index f48f919c3504..2885e7125476 100644 --- a/store/cachekv/store_test.go +++ b/store/cachekv/store_test.go @@ -475,6 +475,10 @@ func doOp(t *testing.T, st types.CacheKVStore, truth corestore.KVStoreWithBatch, err := truth.Set(keyFmt(k), valFmt(k)) require.NoError(t, err) case opSetRange: + if len(args) < 2 { + panic("expected 2 args") + } + start := args[0] end := args[1] setRange(t, st, truth, start, end) @@ -484,6 +488,10 @@ func doOp(t *testing.T, st types.CacheKVStore, truth corestore.KVStoreWithBatch, err := truth.Delete(keyFmt(k)) require.NoError(t, err) case opDelRange: + if len(args) < 2 { + panic("expected 2 args") + } + start := args[0] end := args[1] deleteRange(t, st, truth, start, end) diff --git a/store/go.mod b/store/go.mod index 108f9bb708f6..461c59aa71be 100644 --- a/store/go.mod +++ b/store/go.mod @@ -2,11 +2,9 @@ module cosmossdk.io/store go 1.23 -toolchain go1.23.0 - require ( - cosmossdk.io/core v1.0.0-alpha.2 - cosmossdk.io/core/testing v0.0.0-00010101000000-000000000000 + cosmossdk.io/core v1.0.0-alpha.4 + cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29 cosmossdk.io/errors v1.0.1 cosmossdk.io/log v1.4.1 cosmossdk.io/math v1.3.0 @@ -23,13 +21,13 @@ require ( github.com/stretchr/testify v1.9.0 github.com/tidwall/btree v1.7.0 go.uber.org/mock v0.4.0 - golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 - google.golang.org/grpc v1.66.2 + google.golang.org/grpc v1.67.1 google.golang.org/protobuf v1.34.2 gotest.tools/v3 v3.5.1 ) require ( + cosmossdk.io/schema v0.3.0 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/emicklei/dot v1.6.2 // indirect github.com/fatih/color v1.17.0 // indirect @@ -49,14 +47,12 @@ require ( github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/rogpeppe/go-internal v1.12.0 // indirect github.com/rs/zerolog v1.33.0 // indirect + github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d // indirect golang.org/x/crypto v0.27.0 // indirect + golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 // indirect golang.org/x/net v0.29.0 // indirect golang.org/x/sys v0.25.0 // indirect golang.org/x/text v0.18.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) - -replace cosmossdk.io/core => ../core - -replace cosmossdk.io/core/testing => ../core/testing diff --git a/store/go.sum b/store/go.sum index 4fb7abb073ff..ec2fd3014da1 100644 --- a/store/go.sum +++ b/store/go.sum @@ -1,9 +1,15 @@ +cosmossdk.io/core v1.0.0-alpha.4 h1:9iuroT9ejDYETCsGkzkvs/wAY/5UFl7nCIINFRxyMJY= +cosmossdk.io/core v1.0.0-alpha.4/go.mod h1:3u9cWq1FAVtiiCrDPpo4LhR+9V6k/ycSG4/Y/tREWCY= +cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29 h1:NxxUo0GMJUbIuVg0R70e3cbn9eFTEuMr7ev1AFvypdY= +cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29/go.mod h1:8s2tPeJtSiQuoyPmr2Ag7meikonISO4Fv4MoO8+ORrs= cosmossdk.io/errors v1.0.1 h1:bzu+Kcr0kS/1DuPBtUFdWjzLqyUuCiyHjyJB6srBV/0= cosmossdk.io/errors v1.0.1/go.mod h1:MeelVSZThMi4bEakzhhhE/CKqVv3nOJDA25bIqRDu/U= cosmossdk.io/log v1.4.1 h1:wKdjfDRbDyZRuWa8M+9nuvpVYxrEOwbD/CA8hvhU8QM= cosmossdk.io/log v1.4.1/go.mod h1:k08v0Pyq+gCP6phvdI6RCGhLf/r425UT6Rk/m+o74rU= cosmossdk.io/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE= cosmossdk.io/math v1.3.0/go.mod h1:vnRTxewy+M7BtXBNFybkuhSH4WfedVAAnERHgVFhp3k= +cosmossdk.io/schema v0.3.0 h1:01lcaM4trhzZ1HQTfTV8z6Ma1GziOZ/YmdzBN3F720c= +cosmossdk.io/schema v0.3.0/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= @@ -15,6 +21,9 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r github.com/bufbuild/protocompile v0.14.1 h1:iA73zAf/fyljNjQKwYzUHD6AD4R8KMasmwa/FBatYVw= github.com/bufbuild/protocompile v0.14.1/go.mod h1:ppVdAIhbr2H8asPk6k4pY7t9zB1OU5DoEw9xY/FUi1c= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= github.com/cometbft/cometbft v1.0.0-rc1 h1:pYCXw0rKILceyOzHwd+/fGLag8VYemwLUIX6N7V2REw= @@ -39,11 +48,15 @@ github.com/emicklei/dot v1.6.2/go.mod h1:DeV7GvQtIw4h2u73RKBkkFdvVAz0D9fzeJrgPW6 github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4= github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI= +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/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= @@ -51,17 +64,28 @@ github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69 github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU= github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k= github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= @@ -81,6 +105,8 @@ github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iP github.com/hashicorp/golang-lru v1.0.2/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE= github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/jhump/protoreflect v1.17.0 h1:qOEr613fac2lOuTgWN4tPAtLL7fUSbuJL5X5XumQh94= github.com/jhump/protoreflect v1.17.0/go.mod h1:h9+vUUL38jiBzck8ck+6G/aeMX8Z4QUY/NiJPwPNi+8= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= @@ -115,8 +141,19 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/oklog/run v1.1.0 h1:GEenZ1cK0+q0+wsJew9qUg/DyD8k3JzYsZAi5gYi2mA= github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DVU= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= +github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= +github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= +github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= +github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/petermattis/goid v0.0.0-20221215004737-a150e88a970d h1:htwtWgtQo8YS6JFWWi2DNgY0RwSGJ1ruMoxY6CUUclk= @@ -153,11 +190,12 @@ github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= -github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= +github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d h1:vfofYNRScrDdvS342BElfbETmL1Aiz3i2t0zfRj16Hs= +github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d/go.mod h1:RRCYJbIwD5jmqPI9XoAFR0OcDxqUctll6zUj/+B4S48= github.com/tidwall/btree v1.7.0 h1:L1fkJH/AuEh5zBnnBbmTwQ5Lt+bRJ5A8EWecslvo9iI= github.com/tidwall/btree v1.7.0/go.mod h1:twD9XRA5jj9VUQGELzDO4HPQTNJsoWWfYEL+EUQ2cKY= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= @@ -175,52 +213,85 @@ golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 h1:vr/HnozRka3pE4EsMEg1lgkXJ golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842/go.mod h1:XtvwrStGgqGPLc4cjQfWqZHG1YFdYs6swckp8vpsjnc= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= +golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo= golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0= +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= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +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-20210927094055-39ccf1dd6fa6/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-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/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-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +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/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/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.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= 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= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:pPJltXNxVzT4pK9yD8vR9X75DaWYYmLGMsEvBfFQZzQ= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= -google.golang.org/grpc v1.66.2 h1:3QdXkuq3Bkh7w+ywLdLvM56cmGvQHUMZpiCzt6Rqaoo= -google.golang.org/grpc v1.66.2/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y= +golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f h1:cUMEy+8oS78BWIH9OWazBkzbr090Od9tWBNtZHkOhf0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= +google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E= +google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= +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= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +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.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= @@ -228,10 +299,14 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU= diff --git a/store/iavl/store.go b/store/iavl/store.go index 789e7c5d5eb1..ae6b0b56ff70 100644 --- a/store/iavl/store.go +++ b/store/iavl/store.go @@ -361,8 +361,8 @@ func (st *Store) Query(req *types.RequestQuery) (res *types.ResponseQuery, err e res.ProofOps = getProofFromTree(mtree, req.Data, res.Value != nil) case "/subspace": - pairs := kv.Pairs{ - Pairs: make([]kv.Pair, 0), + pairs := kv.Pairs{ //nolint:staticcheck // We are in store v1. + Pairs: make([]kv.Pair, 0), //nolint:staticcheck // We are in store v1. } subspace := req.Data @@ -370,7 +370,7 @@ func (st *Store) Query(req *types.RequestQuery) (res *types.ResponseQuery, err e iterator := types.KVStorePrefixIterator(st, subspace) for ; iterator.Valid(); iterator.Next() { - pairs.Pairs = append(pairs.Pairs, kv.Pair{Key: iterator.Key(), Value: iterator.Value()}) + pairs.Pairs = append(pairs.Pairs, kv.Pair{Key: iterator.Key(), Value: iterator.Value()}) //nolint:staticcheck // We are in store v1. } if err := iterator.Close(); err != nil { panic(fmt.Errorf("failed to close iterator: %w", err)) diff --git a/store/iavl/store_test.go b/store/iavl/store_test.go index ab6abbde05a6..d0339c59a107 100644 --- a/store/iavl/store_test.go +++ b/store/iavl/store_test.go @@ -478,15 +478,15 @@ func TestIAVLStoreQuery(t *testing.T) { v3 := []byte("val3") ksub := []byte("key") - KVs0 := kv.Pairs{} - KVs1 := kv.Pairs{ - Pairs: []kv.Pair{ + KVs0 := kv.Pairs{} //nolint:staticcheck // We are in store v1. + KVs1 := kv.Pairs{ //nolint:staticcheck // We are in store v1. + Pairs: []kv.Pair{ //nolint:staticcheck // We are in store v1. {Key: k1, Value: v1}, {Key: k2, Value: v2}, }, } - KVs2 := kv.Pairs{ - Pairs: []kv.Pair{ + KVs2 := kv.Pairs{ //nolint:staticcheck // We are in store v1. + Pairs: []kv.Pair{ //nolint:staticcheck // We are in store v1. {Key: k1, Value: v3}, {Key: k2, Value: v2}, }, @@ -639,8 +639,6 @@ func TestSetInitialVersion(t *testing.T) { } for _, tc := range testCases { - tc := tc - t.Run(tc.name, func(t *testing.T) { db := coretesting.NewMemDB() store := tc.storeFn(db) diff --git a/store/internal/maps/maps.go b/store/internal/maps/maps.go index 6db2be666cae..f2c6117c737b 100644 --- a/store/internal/maps/maps.go +++ b/store/internal/maps/maps.go @@ -14,13 +14,13 @@ import ( // merkleMap defines a merkle-ized tree from a map. Leave values are treated as // hash(key) | hash(value). Leaves are sorted before Merkle hashing. type merkleMap struct { - kvs kv.Pairs + kvs kv.Pairs //nolint:staticcheck // We are in store v1. sorted bool } func newMerkleMap() *merkleMap { return &merkleMap{ - kvs: kv.Pairs{}, + kvs: kv.Pairs{}, //nolint:staticcheck // We are in store v1. sorted: false, } } @@ -38,7 +38,7 @@ func (sm *merkleMap) set(key string, value []byte) { // and make a determination to fetch or not. vhash := sha256.Sum256(value) - sm.kvs.Pairs = append(sm.kvs.Pairs, kv.Pair{ + sm.kvs.Pairs = append(sm.kvs.Pairs, kv.Pair{ //nolint:staticcheck // We are in store v1. Key: byteKey, Value: vhash[:], }) @@ -61,7 +61,7 @@ func (sm *merkleMap) sort() { // hashKVPairs hashes a kvPair and creates a merkle tree where the leaves are // byte slices. -func hashKVPairs(kvs kv.Pairs) []byte { +func hashKVPairs(kvs kv.Pairs) []byte { //nolint:staticcheck // We are in store v1. kvsH := make([][]byte, len(kvs.Pairs)) for i, kvp := range kvs.Pairs { kvsH[i] = KVPair(kvp).Bytes() @@ -76,13 +76,13 @@ func hashKVPairs(kvs kv.Pairs) []byte { // Leaves are `hash(key) | hash(value)`. // Leaves are sorted before Merkle hashing. type simpleMap struct { - Kvs kv.Pairs + Kvs kv.Pairs //nolint:staticcheck // We are in store v1. sorted bool } func newSimpleMap() *simpleMap { return &simpleMap{ - Kvs: kv.Pairs{}, + Kvs: kv.Pairs{}, //nolint:staticcheck // We are in store v1. sorted: false, } } @@ -99,7 +99,7 @@ func (sm *simpleMap) Set(key string, value []byte) { // and make a determination to fetch or not. vhash := sha256.Sum256(value) - sm.Kvs.Pairs = append(sm.Kvs.Pairs, kv.Pair{ + sm.Kvs.Pairs = append(sm.Kvs.Pairs, kv.Pair{ //nolint:staticcheck // We are in store v1. Key: byteKey, Value: vhash[:], }) @@ -122,10 +122,10 @@ func (sm *simpleMap) Sort() { // KVPairs returns a copy of sorted KVPairs. // NOTE these contain the hashed key and value. -func (sm *simpleMap) KVPairs() kv.Pairs { +func (sm *simpleMap) KVPairs() kv.Pairs { //nolint:staticcheck // We are in store v1. sm.Sort() - kvs := kv.Pairs{ - Pairs: make([]kv.Pair, len(sm.Kvs.Pairs)), + kvs := kv.Pairs{ //nolint:staticcheck // We are in store v1. + Pairs: make([]kv.Pair, len(sm.Kvs.Pairs)), //nolint:staticcheck // We are in store v1. } copy(kvs.Pairs, sm.Kvs.Pairs) @@ -137,12 +137,12 @@ func (sm *simpleMap) KVPairs() kv.Pairs { // KVPair is a local extension to KVPair that can be hashed. // Key and value are length prefixed and concatenated, // then hashed. -type KVPair kv.Pair +type KVPair kv.Pair //nolint:staticcheck // We are in store v1. // NewKVPair takes in a key and value and creates a kv.Pair // wrapped in the local extension KVPair func NewKVPair(key, value []byte) KVPair { - return KVPair(kv.Pair{ + return KVPair(kv.Pair{ //nolint:staticcheck // We are in store v1. Key: key, Value: value, }) diff --git a/store/internal/proofs/helpers.go b/store/internal/proofs/helpers.go index a87a692212ce..b82c96fe9c49 100644 --- a/store/internal/proofs/helpers.go +++ b/store/internal/proofs/helpers.go @@ -1,10 +1,10 @@ package proofs import ( - "sort" + "maps" + "slices" cmtprotocrypto "github.com/cometbft/cometbft/api/cometbft/crypto/v1" - "golang.org/x/exp/maps" "cosmossdk.io/math/unsafe" sdkmaps "cosmossdk.io/store/internal/maps" @@ -47,9 +47,7 @@ const ( ) func SortedKeys(data map[string][]byte) []string { - keys := maps.Keys(data) - sort.Strings(keys) - return keys + return slices.Sorted(maps.Keys(data)) } func CalcRoot(data map[string][]byte) []byte { diff --git a/store/listenkv/store_test.go b/store/listenkv/store_test.go index 3425097db100..7b1b17fd6755 100644 --- a/store/listenkv/store_test.go +++ b/store/listenkv/store_test.go @@ -19,7 +19,7 @@ func bz(s string) []byte { return []byte(s) } func keyFmt(i int) []byte { return bz(fmt.Sprintf("key%0.8d", i)) } func valFmt(i int) []byte { return bz(fmt.Sprintf("value%0.8d", i)) } -var kvPairs = []kv.Pair{ +var kvPairs = []kv.Pair{ //nolint:staticcheck // We are in store v1. {Key: keyFmt(1), Value: valFmt(1)}, {Key: keyFmt(2), Value: valFmt(2)}, {Key: keyFmt(3), Value: valFmt(3)}, diff --git a/store/pruning/manager_test.go b/store/pruning/manager_test.go index 19cbe5deb42f..0f62a36c5b07 100644 --- a/store/pruning/manager_test.go +++ b/store/pruning/manager_test.go @@ -75,7 +75,7 @@ func TestStrategies(t *testing.T) { } for name, tc := range testcases { - tc := tc // Local copy to avoid shadowing. + // Local copy to avoid shadowing. t.Run(name, func(t *testing.T) { t.Parallel() diff --git a/store/rootmulti/snapshot_test.go b/store/rootmulti/snapshot_test.go index 35a2a0c569f7..fc00f5be25d9 100644 --- a/store/rootmulti/snapshot_test.go +++ b/store/rootmulti/snapshot_test.go @@ -142,7 +142,6 @@ func TestMultistoreSnapshot_Checksum(t *testing.T) { }}, } for _, tc := range testcases { - tc := tc t.Run(fmt.Sprintf("Format %v", tc.format), func(t *testing.T) { ch := make(chan io.ReadCloser) go func() { @@ -177,7 +176,6 @@ func TestMultistoreSnapshot_Errors(t *testing.T) { "unknown height": {9, nil}, } for name, tc := range testcases { - tc := tc t.Run(name, func(t *testing.T) { err := store.Snapshot(tc.height, nil) require.Error(t, err) diff --git a/store/rootmulti/store.go b/store/rootmulti/store.go index 0c8a1ef3a3b0..d23bcc57b090 100644 --- a/store/rootmulti/store.go +++ b/store/rootmulti/store.go @@ -1147,7 +1147,9 @@ func (rs *Store) flushMetadata(db corestore.KVStoreWithBatch, version int64, cIn rs.logger.Debug("flushing metadata", "height", version) batch := db.NewBatch() defer func() { - _ = batch.Close() + if err := batch.Close(); err != nil { + rs.logger.Error("call flushMetadata error on batch close", "err", err) + } }() if cInfo != nil { diff --git a/store/rootmulti/store_test.go b/store/rootmulti/store_test.go index cd2029a5f707..31d24ed1205c 100644 --- a/store/rootmulti/store_test.go +++ b/store/rootmulti/store_test.go @@ -524,8 +524,6 @@ func TestMultiStore_Pruning(t *testing.T) { } for _, tc := range testCases { - tc := tc - t.Run(tc.name, func(t *testing.T) { db := coretesting.NewMemDB() ms := newMultiStoreWithMounts(db, tc.po) diff --git a/store/snapshots/manager.go b/store/snapshots/manager.go index 4d75690c396e..17c318a94bec 100644 --- a/store/snapshots/manager.go +++ b/store/snapshots/manager.go @@ -388,8 +388,11 @@ func (m *Manager) doRestoreSnapshot(snapshot types.Snapshot, chChunks <-chan io. return errorsmod.Wrapf(err, "extension %s restore", metadata.Name) } - if nextItem.GetExtensionPayload() != nil { + payload := nextItem.GetExtensionPayload() + if payload != nil && len(payload.Payload) != 0 { return fmt.Errorf("extension %s don't exhausted payload stream", metadata.Name) + } else { + break } } return nil diff --git a/store/streaming/abci/README.md b/store/streaming/abci/README.md index 08aaf12e8a30..1ee13d659766 100644 --- a/store/streaming/abci/README.md +++ b/store/streaming/abci/README.md @@ -27,7 +27,7 @@ To generate the stubs the local client implementation can call, run the followin make proto-gen ``` -For other languages you'll need to [download](https://github.com/cosmos/cosmos-sdk/blob/main/third_party/proto/README.md) +For other languages you'll need to [download](https://github.com/cosmos/cosmos-sdk/blob/main/proto/README.md#generate) the CosmosSDK protos into your project and compile. For language specific compilation instructions visit [https://github.com/grpc](https://github.com/grpc) and look in the `examples` folder of your language of choice `https://github.com/grpc/grpc-{language}/tree/master/examples` and [https://grpc.io](https://grpc.io) diff --git a/store/tracekv/store_test.go b/store/tracekv/store_test.go index ae4136cce87f..5ad933cb67b0 100644 --- a/store/tracekv/store_test.go +++ b/store/tracekv/store_test.go @@ -21,7 +21,7 @@ func bz(s string) []byte { return []byte(s) } func keyFmt(i int) []byte { return bz(fmt.Sprintf("key%0.8d", i)) } func valFmt(i int) []byte { return bz(fmt.Sprintf("value%0.8d", i)) } -var kvPairs = []kv.Pair{ +var kvPairs = []kv.Pair{ //nolint:staticcheck // We are in store v1. {Key: keyFmt(1), Value: valFmt(1)}, {Key: keyFmt(2), Value: valFmt(2)}, {Key: keyFmt(3), Value: valFmt(3)}, diff --git a/store/types/gas_test.go b/store/types/gas_test.go index f4b5a6abe5ba..a4f63ab6d999 100644 --- a/store/types/gas_test.go +++ b/store/types/gas_test.go @@ -47,7 +47,6 @@ func TestGasMeter(t *testing.T) { used := uint64(0) for unum, usage := range tc.usage { - usage := usage used += usage require.NotPanics(t, func() { meter.ConsumeGas(usage, "") }, "Not exceeded limit but panicked. tc #%d, usage #%d", tcnum, unum) require.Equal(t, used, meter.GasConsumed(), "Gas consumption not match. tc #%d, usage #%d", tcnum, unum) diff --git a/store/types/iterator_test.go b/store/types/iterator_test.go index e520acd85792..f8a1af65b83a 100644 --- a/store/types/iterator_test.go +++ b/store/types/iterator_test.go @@ -84,7 +84,6 @@ func TestPaginatedIterator(t *testing.T) { reverse: true, }, } { - tc := tc t.Run(tc.desc, func(t *testing.T) { var iter types.Iterator if tc.reverse { diff --git a/store/types/store_test.go b/store/types/store_test.go index b6304d131bc2..4a77c7babea8 100644 --- a/store/types/store_test.go +++ b/store/types/store_test.go @@ -53,7 +53,6 @@ func TestStoreUpgrades(t *testing.T) { } for name, tc := range cases { - tc := tc t.Run(name, func(t *testing.T) { for _, r := range tc.expectAdd { assert.Equal(t, tc.upgrades.IsAdded(r.key), true) diff --git a/store/v2/README.md b/store/v2/README.md index 213f55d05aeb..eb8495c9adc4 100644 --- a/store/v2/README.md +++ b/store/v2/README.md @@ -1,7 +1,7 @@ # Store The `store` package contains the implementation of store/v2, which is the SDK's -abstraction around managing historical and committed state. See [ADR-065](../docs/architecture/adr-065-store-v2.md) +abstraction around managing historical and committed state. See [ADR-065](../../docs/architecture/adr-065-store-v2.md) and [Store v2 Design](https://docs.google.com/document/d/1l6uXIjTPHOOWM5N4sUUmUfCZvePoa5SNfIEtmgvgQSU/edit#heading=h.nz8dqy6wa4g1) for a high-level overview of the design and rationale. ## Usage @@ -42,21 +42,26 @@ sequenceDiagram end ``` -`Prune store keys` does not remove the data from the SC and SS instantly. It only +`PruneStoreKeys` does not remove the data from the SC and SS instantly. It only marks the store keys as pruned. The actual data removal is done by the pruning process of the underlying SS and SC. ## Migration - +The migration from store/v1 to store/v2 is supported by the `MigrationManager` in +the `migration` package. See [Migration Manager](./migration/README.md) for more details. ## Pruning The `root.Store` is NOT responsible for pruning. Rather, pruning is the responsibility of the underlying SS and SC layers. This means pruning can be implementation specific, -such as being synchronous or asynchronous. +such as being synchronous or asynchronous. See [Pruning Manager](./pruning/README.md) for more details. +## State Sync + +The `root.Store` is NOT responsible for state sync. See [Snapshots Manager](./snapshots/README.md) +for more details. ## Test Coverage diff --git a/store/v2/commitment/README.md b/store/v2/commitment/README.md index c9bcf111b4ed..bf730ccb3742 100644 --- a/store/v2/commitment/README.md +++ b/store/v2/commitment/README.md @@ -28,7 +28,11 @@ See this [section](https://docs.google.com/document/d/1l6uXIjTPHOOWM5N4sUUmUfCZv ## Pruning - +Pruning is the process of efficiently managing and removing outdated data from the +State Commitment (SC). To facilitate this, the SC backend must implement the `Pruner` +interface, allowing the `PruningManager` to execute data pruning operations according +to the specified `PruningOption`. Optionally, the SC backend can implement the +`PausablePruner` interface to pause pruning during a commit. ## State Sync diff --git a/store/v2/commitment/metadata.go b/store/v2/commitment/metadata.go index 7462252e962b..642e6b630dac 100644 --- a/store/v2/commitment/metadata.go +++ b/store/v2/commitment/metadata.go @@ -2,6 +2,7 @@ package commitment import ( "bytes" + "errors" "fmt" corestore "cosmossdk.io/core/store" @@ -81,10 +82,7 @@ func (m *MetadataStore) flushCommitInfo(version uint64, cInfo *proof.CommitInfo) batch := m.kv.NewBatch() defer func() { - cErr := batch.Close() - if err == nil { - err = cErr - } + err = errors.Join(err, batch.Close()) }() cInfoKey := []byte(fmt.Sprintf(commitInfoKeyFmt, version)) value, err := cInfo.Marshal() @@ -113,7 +111,7 @@ func (m *MetadataStore) flushCommitInfo(version uint64, cInfo *proof.CommitInfo) func (m *MetadataStore) flushRemovedStoreKeys(version uint64, storeKeys []string) (err error) { batch := m.kv.NewBatch() defer func() { - err = batch.Close() + err = errors.Join(err, batch.Close()) }() for _, storeKey := range storeKeys { @@ -155,9 +153,7 @@ func (m *MetadataStore) deleteRemovedStoreKeys(version uint64, removeStore func( batch := m.kv.NewBatch() defer func() { - if berr := batch.Close(); berr != nil { - err = berr - } + err = errors.Join(err, batch.Close()) }() for _, storeKey := range removedStoreKeys { if err := removeStore(storeKey, version); err != nil { diff --git a/store/v2/go.mod b/store/v2/go.mod index 6cc9d1d067a3..1a0d84d80a8b 100644 --- a/store/v2/go.mod +++ b/store/v2/go.mod @@ -3,8 +3,8 @@ module cosmossdk.io/store/v2 go 1.23 require ( - cosmossdk.io/core v1.0.0-alpha.2 - cosmossdk.io/core/testing v0.0.0-00010101000000-000000000000 + cosmossdk.io/core v1.0.0-alpha.3 + cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29 cosmossdk.io/errors/v2 v2.0.0-20240731132947-df72853b3ca5 cosmossdk.io/log v1.4.1 github.com/cockroachdb/pebble v1.1.0 @@ -24,6 +24,7 @@ require ( ) require ( + cosmossdk.io/schema v0.3.0 // indirect github.com/DataDog/zstd v1.5.5 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect @@ -49,9 +50,9 @@ require ( github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/client_golang v1.20.3 // indirect + github.com/prometheus/client_golang v1.20.4 // indirect github.com/prometheus/client_model v0.6.1 // indirect - github.com/prometheus/common v0.59.1 // indirect + github.com/prometheus/common v0.60.0 // indirect github.com/prometheus/procfs v0.15.1 // indirect github.com/rogpeppe/go-internal v1.12.0 // indirect github.com/rs/zerolog v1.33.0 // indirect @@ -63,5 +64,3 @@ require ( google.golang.org/protobuf v1.34.2 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) - -replace cosmossdk.io/core/testing => ../../core/testing diff --git a/store/v2/go.sum b/store/v2/go.sum index ce946b663c0c..8211266d41a1 100644 --- a/store/v2/go.sum +++ b/store/v2/go.sum @@ -1,9 +1,13 @@ -cosmossdk.io/core v1.0.0-alpha.2 h1:epU0Xwces4Rgl5bMhHHkXGaGDcyucNGlC/JDH+Suckg= -cosmossdk.io/core v1.0.0-alpha.2/go.mod h1:abgLjeFLhtuKIYZWSPlVUgQBrKObO7ULV35KYfexE90= +cosmossdk.io/core v1.0.0-alpha.3 h1:pnxaYAas7llXgVz1lM7X6De74nWrhNKnB3yMKe4OUUA= +cosmossdk.io/core v1.0.0-alpha.3/go.mod h1:3u9cWq1FAVtiiCrDPpo4LhR+9V6k/ycSG4/Y/tREWCY= +cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29 h1:NxxUo0GMJUbIuVg0R70e3cbn9eFTEuMr7ev1AFvypdY= +cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29/go.mod h1:8s2tPeJtSiQuoyPmr2Ag7meikonISO4Fv4MoO8+ORrs= cosmossdk.io/errors/v2 v2.0.0-20240731132947-df72853b3ca5 h1:IQNdY2kB+k+1OM2DvqFG1+UgeU1JzZrWtwuWzI3ZfwA= cosmossdk.io/errors/v2 v2.0.0-20240731132947-df72853b3ca5/go.mod h1:0CuYKkFHxc1vw2JC+t21THBCALJVROrWVR/3PQ1urpc= cosmossdk.io/log v1.4.1 h1:wKdjfDRbDyZRuWa8M+9nuvpVYxrEOwbD/CA8hvhU8QM= cosmossdk.io/log v1.4.1/go.mod h1:k08v0Pyq+gCP6phvdI6RCGhLf/r425UT6Rk/m+o74rU= +cosmossdk.io/schema v0.3.0 h1:01lcaM4trhzZ1HQTfTV8z6Ma1GziOZ/YmdzBN3F720c= +cosmossdk.io/schema v0.3.0/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/DataDog/zstd v1.5.5 h1:oWf5W7GtOLgp6bciQYDmhHHjdhYkALu6S/5Ni9ZgSvQ= github.com/DataDog/zstd v1.5.5/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= @@ -176,8 +180,8 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= -github.com/prometheus/client_golang v1.20.3 h1:oPksm4K8B+Vt35tUhw6GbSNSgVlVSBH0qELP/7u83l4= -github.com/prometheus/client_golang v1.20.3/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_golang v1.20.4 h1:Tgh3Yr67PaOv/uTqloMsCEdeuFTatm5zIq5+qNN23vI= +github.com/prometheus/client_golang v1.20.4/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -185,8 +189,8 @@ github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= -github.com/prometheus/common v0.59.1 h1:LXb1quJHWm1P6wq/U824uxYi4Sg0oGvNeUm1z5dJoX0= -github.com/prometheus/common v0.59.1/go.mod h1:GpWM7dewqmVYcd7SmRaiWVe9SSqjf0UrwnYnpEZNuT0= +github.com/prometheus/common v0.60.0 h1:+V9PAREWNvJMAuJ1x1BaWl9dewMW4YrHZQbx0sJNllA= +github.com/prometheus/common v0.60.0/go.mod h1:h0LYf1R1deLSKtD4Vdg8gy4RuOvENW2J/h19V5NADQw= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/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= @@ -241,8 +245,8 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE= -golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg= +golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo= +golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0= 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= diff --git a/store/v2/migration/README.md b/store/v2/migration/README.md new file mode 100644 index 000000000000..9db8c9874a8c --- /dev/null +++ b/store/v2/migration/README.md @@ -0,0 +1,111 @@ +# Migration Manager + +The `migration` package contains the `migration.Manager`, which is responsible +for migrating data from `store/v1` to `store/v2`. To ensure a smooth transition, +the process is designed to **lazily** migrate data in the background without blocking +`root.Store` operations. + +## Overview + +The migration process involves several steps: + +1. **Create a snapshot** of the current state while `Commit` operations continue to + function with `store/v1`. +2. **Restore the snapshot** into the new StateStorage (SS) and StateCommitment (SC). +3. **Sync recent state changes** from `store/v1` to the new SS and SC. +4. After syncing, the `Commit` operation will be switched to the new `store/v2`. + +Taking a snapshot is a lightweight operation. The snapshot is not stored on disk but +consumed by the `Restore` process, which replays state changes to the new SS and SC. + +> **Note:** After migration, `store/v2` does **not** support historical queries. +If historical data access is required, a full state migration to `store/v2` is necessary. + +## Usage + +You can create a new `migration.Manager` by calling the following function: + +```go +func NewManager( + db corestore.KVStoreWithBatch, + sm *snapshots.Manager, + ss *storage.StorageStore, + sc *commitment.CommitStore, + logger log.Logger +) *Manager +``` + +* `sc` (Commitment Store) can be `nil`. In that case, the Manager will migrate only + the state storage. +* The migration process is lazy, meaning data is migrated in the background while + `root.Store` remains fully operational. + +To initiate the migration process, call the `Start` method: + +```go +func (m *Manager) Start(ctx context.Context) error +``` + +> **Note:** It should be called by the RootStore, running in the background. + +## Migration Flow + +```mermaid +sequenceDiagram + autonumber + + participant A as RootStore + participant B as MigrationManager + participant C as SnapshotsManager + participant D as StateCommitment + participant E as StateStorage + + A->>B: Start + loop Old Data Migration + B->>C: Create Snapshot + C->>B: Stream Snapshot + B->>D: State Sync (Restore) + B->>E: Write Changeset (Restore) + end + + loop New Commit Data Sync + A->>B: Commit(Changeset) + B->>B: Store Changeset + B->>D: Commit Changeset + B->>E: Write Changeset + end + + B->>A: Switch to new store/v2 +``` + +## Key Considerations + +### Laziness and Background Operation + +The migration is performed lazily, meaning it occurs in the background without +interrupting the current operations on root.Store. This allows the chain to continue +running while data is gradually migrated to `store/v2`. State synchronization ensures +that any new state changes during the migration are also applied to `store/v2`. + +However, note that there may be a performance impact depending on the size of the data +being migrated, and it’s essential to monitor the migration process in production +environments. + +### Handling Failures and Rollbacks + +It is important to consider how the migration manager handles errors or system failures +during the migration process: + +* If the migration fails, there is no impact on the existing `store/v1` operations, + but need to restart the migration process from the scratch. +* In the event of a critical failure after migration, a rollback may not be possible, + and it is needed to keep the `store/v1` backup for a certain period. + +### Impact on Historical Queries + +After the migration, the new `store/v2` does not support historical queries. +This limitation should be clearly understood before starting the migration process, +especially if the node relies on historical data for any operations. + +If historical queries are required, users must fully migrate all historical data to `store/v2`. +Alternatively, keeping store/v1 accessible for historical queries could be an option. \ No newline at end of file diff --git a/store/v2/migration/manager.go b/store/v2/migration/manager.go index a7ce8204a4b3..237dbd1e3606 100644 --- a/store/v2/migration/manager.go +++ b/store/v2/migration/manager.go @@ -185,10 +185,7 @@ func (m *Manager) writeChangeset() error { // yet not in the for-loop which can leave resource lingering. err = func() (err error) { defer func() { - cErr := batch.Close() - if err == nil { - err = cErr - } + err = errors.Join(err, batch.Close()) }() if err := batch.Set(csKey, csBytes); err != nil { diff --git a/store/v2/root/factory.go b/store/v2/root/factory.go index 4dfa01966314..e6f86917ab0d 100644 --- a/store/v2/root/factory.go +++ b/store/v2/root/factory.go @@ -109,6 +109,8 @@ func CreateRootStore(opts *FactoryOptions) (store.RootStore, error) { return nil, err } ssDb, err = rocksdb.New(dir) + default: + return nil, fmt.Errorf("unknown storage type: %s", opts.Options.SSType) } if err != nil { return nil, err @@ -168,12 +170,12 @@ func CreateRootStore(opts *FactoryOptions) (store.RootStore, error) { } oldTrees[string(key)] = tree } + sc, err = commitment.NewCommitStore(trees, oldTrees, opts.SCRawDB, opts.Logger) if err != nil { return nil, err } pm := pruning.NewManager(sc, ss, storeOpts.SCPruningOption, storeOpts.SSPruningOption) - return New(opts.Logger, ss, sc, pm, nil, nil) } diff --git a/store/v2/root/store_test.go b/store/v2/root/store_test.go index eddaea730652..e8cf34e014e0 100644 --- a/store/v2/root/store_test.go +++ b/store/v2/root/store_test.go @@ -456,7 +456,6 @@ func (s *RootStoreTestSuite) TestPrune() { } for _, tc := range testCases { - tc := tc s.newStoreWithPruneConfig(&tc.po) diff --git a/store/v2/snapshots/manager.go b/store/v2/snapshots/manager.go index 7e12e4503de8..85d2cf26be25 100644 --- a/store/v2/snapshots/manager.go +++ b/store/v2/snapshots/manager.go @@ -437,8 +437,11 @@ func (m *Manager) doRestoreSnapshot(snapshot types.Snapshot, chChunks <-chan io. return errorsmod.Wrapf(err, "extension %s restore", metadata.Name) } - if nextItem.GetExtensionPayload() != nil { + payload := nextItem.GetExtensionPayload() + if payload != nil && len(payload.Payload) != 0 { return fmt.Errorf("extension %s don't exhausted payload stream", metadata.Name) + } else { + break } } diff --git a/store/v2/sonar-project.properties b/store/v2/sonar-project.properties index 008f93fc9fe0..a341f6f55738 100644 --- a/store/v2/sonar-project.properties +++ b/store/v2/sonar-project.properties @@ -1,4 +1,4 @@ -sonar.projectKey=cosmos-sdk-store +sonar.projectKey=cosmos-sdk-store-v2 sonar.organization=cosmos sonar.projectName=Cosmos SDK - Store diff --git a/store/v2/storage/README.md b/store/v2/storage/README.md index 48606d6c19c1..5467bff24a05 100644 --- a/store/v2/storage/README.md +++ b/store/v2/storage/README.md @@ -70,13 +70,10 @@ Iterate/backend_rocksdb_versiondb_opts-10 778ms ± 0% ## Pruning -Pruning is an implementation and responsibility of the underlying SS backend. -Specifically, the `StorageStore` accepts `store.PruningOption` which defines the -pruning configuration. During `ApplyChangeset`, the `StorageStore` will check if -pruning should occur based on the current height being committed. If so, it will -delegate a `Prune` call on the underlying SS backend, which can be defined specific -to the implementation, e.g. asynchronous or synchronous. - +Pruning is the process of efficiently managing and removing outdated or redundant +data from the State Storage (SS). To facilitate this, the SS backend must implement +the `Pruner` interface, allowing the `PruningManager` to execute data pruning operations +according to the specified `PruningOption`. ## State Sync diff --git a/store/v2/storage/pebbledb/db.go b/store/v2/storage/pebbledb/db.go index ebcd242af243..e5fd49ca3e5d 100644 --- a/store/v2/storage/pebbledb/db.go +++ b/store/v2/storage/pebbledb/db.go @@ -68,27 +68,27 @@ func New(dataDir string) (*Database, error) { return nil, fmt.Errorf("failed to open PebbleDB: %w", err) } - pruneHeight, err := getPruneHeight(db) + earliestVersion, err := getEarliestVersion(db) if err != nil { - return nil, fmt.Errorf("failed to get prune height: %w", err) + return nil, fmt.Errorf("failed to get the earliest version: %w", err) } return &Database{ storage: db, - earliestVersion: pruneHeight + 1, + earliestVersion: earliestVersion, sync: true, }, nil } func NewWithDB(storage *pebble.DB, sync bool) *Database { - pruneHeight, err := getPruneHeight(storage) + earliestVersion, err := getEarliestVersion(storage) if err != nil { - panic(fmt.Errorf("failed to get prune height: %w", err)) + panic(fmt.Errorf("failed to get the earliest version: %w", err)) } return &Database{ storage: storage, - earliestVersion: pruneHeight + 1, + earliestVersion: earliestVersion, sync: sync, } } @@ -203,7 +203,7 @@ func (db *Database) Get(storeKey []byte, targetVersion uint64, key []byte) ([]by // database in order to delete them. // // See: https://github.com/cockroachdb/cockroach/blob/33623e3ee420174a4fd3226d1284b03f0e3caaac/pkg/storage/mvcc.go#L3182 -func (db *Database) Prune(version uint64) error { +func (db *Database) Prune(version uint64) (err error) { itr, err := db.storage.NewIter(&pebble.IterOptions{LowerBound: []byte("s/k:")}) if err != nil { return err @@ -211,7 +211,9 @@ func (db *Database) Prune(version uint64) error { defer itr.Close() batch := db.storage.NewBatch() - defer batch.Close() + defer func() { + err = errors.Join(err, batch.Close()) + }() var ( batchCounter int @@ -331,9 +333,11 @@ func (db *Database) ReverseIterator(storeKey []byte, version uint64, start, end return newPebbleDBIterator(itr, storePrefix(storeKey), start, end, version, db.earliestVersion, true), nil } -func (db *Database) PruneStoreKeys(storeKeys []string, version uint64) error { +func (db *Database) PruneStoreKeys(storeKeys []string, version uint64) (err error) { batch := db.storage.NewBatch() - defer batch.Close() + defer func() { + err = errors.Join(err, batch.Close()) + }() for _, storeKey := range storeKeys { if err := batch.Set([]byte(fmt.Sprintf("%s%s", encoding.BuildPrefixWithVersion(removedStoreKeyPrefix, version), storeKey)), []byte{}, nil); err != nil { @@ -352,7 +356,10 @@ func prependStoreKey(storeKey, key []byte) []byte { return []byte(fmt.Sprintf("%s%s", storePrefix(storeKey), key)) } -func getPruneHeight(storage *pebble.DB) (uint64, error) { +// getEarliestVersion returns the earliest version set in the database. +// It is calculated by prune height + 1. If the prune height is not set, it +// returns 0. +func getEarliestVersion(storage *pebble.DB) (uint64, error) { bz, closer, err := storage.Get([]byte(pruneHeightKey)) if err != nil { if errors.Is(err, pebble.ErrNotFound) { @@ -367,7 +374,7 @@ func getPruneHeight(storage *pebble.DB) (uint64, error) { return 0, closer.Close() } - return binary.LittleEndian.Uint64(bz), closer.Close() + return binary.LittleEndian.Uint64(bz) + 1, closer.Close() } func valTombstoned(value []byte) bool { @@ -428,9 +435,11 @@ func getMVCCSlice(db *pebble.DB, storeKey, key []byte, version uint64) ([]byte, return slices.Clone(value), err } -func (db *Database) deleteRemovedStoreKeys(version uint64) error { +func (db *Database) deleteRemovedStoreKeys(version uint64) (err error) { batch := db.storage.NewBatch() - defer batch.Close() + defer func() { + err = errors.Join(err, batch.Close()) + }() end := encoding.BuildPrefixWithVersion(removedStoreKeyPrefix, version+1) storeKeyIter, err := db.storage.NewIter(&pebble.IterOptions{LowerBound: []byte(removedStoreKeyPrefix), UpperBound: end}) diff --git a/store/v2/storage/pebbledb/iterator.go b/store/v2/storage/pebbledb/iterator.go index 6b16805e9d40..6cafe196a20b 100644 --- a/store/v2/storage/pebbledb/iterator.go +++ b/store/v2/storage/pebbledb/iterator.go @@ -82,6 +82,12 @@ func newPebbleDBIterator(src *pebble.Iterator, prefix, mvccStart, mvccEnd []byte // so there exists at least one version of currKey SeekLT may move to. itr.valid = itr.source.SeekLT(MVCCEncode(currKey, itr.version+1)) } + + // The cursor might now be pointing at a key/value pair that is tombstoned. + // If so, we must move the cursor. + if itr.valid && itr.cursorTombstoned() { + itr.Next() + } } return itr } diff --git a/store/v2/storage/storage_test_suite.go b/store/v2/storage/storage_test_suite.go index 6b4247fffc8d..08f455ca12ca 100644 --- a/store/v2/storage/storage_test_suite.go +++ b/store/v2/storage/storage_test_suite.go @@ -485,6 +485,33 @@ func (s *StorageTestSuite) TestDatabaseIterator_ForwardIterationHigher() { s.Require().Equal(0, count) } +func (s *StorageTestSuite) TestDatabaseIterator_WithDelete() { + db, err := s.NewDB(s.T().TempDir()) + s.Require().NoError(err) + defer db.Close() + + dbApplyChangeset(s.T(), db, 1, storeKey1, [][]byte{[]byte("keyA")}, [][]byte{[]byte("value001")}) + dbApplyChangeset(s.T(), db, 2, storeKey1, [][]byte{[]byte("keyA")}, [][]byte{nil}) // delete + + itr, err := db.Iterator(storeKey1Bytes, 1, nil, nil) + s.Require().NoError(err) + + count := 0 + for ; itr.Valid(); itr.Next() { + count++ + } + s.Require().Equal(1, count) + + itr, err = db.Iterator(storeKey1Bytes, 2, nil, nil) + s.Require().NoError(err) + + count = 0 + for ; itr.Valid(); itr.Next() { + count++ + } + s.Require().Equal(0, count) +} + func (s *StorageTestSuite) TestDatabase_IteratorNoDomain() { db, err := s.NewDB(s.T().TempDir()) s.Require().NoError(err) diff --git a/telemetry/wrapper.go b/telemetry/wrapper.go index 1e37cb8cc296..4362c46a4413 100644 --- a/telemetry/wrapper.go +++ b/telemetry/wrapper.go @@ -8,11 +8,9 @@ import ( // Common metric key constants const ( - MetricKeyBeginBlocker = "begin_blocker" - MetricKeyEndBlocker = "end_blocker" - MetricKeyPrepareCheckStater = "prepare_check_stater" - MetricKeyPrecommiter = "precommiter" - MetricLabelNameModule = "module" + MetricKeyBeginBlocker = "begin_blocker" + MetricKeyEndBlocker = "end_blocker" + MetricLabelNameModule = "module" ) // NewLabel creates a new instance of Label with name and value diff --git a/tests/e2e/accounts/base_account_test.go b/tests/e2e/accounts/base_account_test.go index 80c181e0bc6e..bfaee8bbb357 100644 --- a/tests/e2e/accounts/base_account_test.go +++ b/tests/e2e/accounts/base_account_test.go @@ -6,6 +6,7 @@ import ( "math/rand" "testing" + gogoproto "github.com/cosmos/gogoproto/proto" gogoany "github.com/cosmos/gogoproto/types/any" "cosmossdk.io/simapp" diff --git a/tests/e2e/accounts/multisig/test_suite.go b/tests/e2e/accounts/multisig/test_suite.go index 3aa23f147d25..d2e6debb6de6 100644 --- a/tests/e2e/accounts/multisig/test_suite.go +++ b/tests/e2e/accounts/multisig/test_suite.go @@ -10,7 +10,6 @@ import ( "cosmossdk.io/core/transaction" "cosmossdk.io/math" "cosmossdk.io/simapp" - multisigaccount "cosmossdk.io/x/accounts/defaults/multisig" v1 "cosmossdk.io/x/accounts/defaults/multisig/v1" "cosmossdk.io/x/bank/testutil" @@ -76,7 +75,7 @@ func (s *E2ETestSuite) initAccount(ctx context.Context, sender []byte, membersPo members = append(members, &v1.Member{Address: addrStr, Weight: power}) } - _, accountAddr, err := s.app.AccountsKeeper.Init(ctx, multisigaccount.MULTISIG_ACCOUNT, sender, + _, accountAddr, err := s.app.AccountsKeeper.Init(ctx, "multisig", sender, &v1.MsgInit{ Members: members, Config: &v1.Config{ diff --git a/tests/e2e/auth/keeper/app_config.go b/tests/e2e/auth/keeper/app_config.go index 7d761d63129e..051fb5efeac7 100644 --- a/tests/e2e/auth/keeper/app_config.go +++ b/tests/e2e/auth/keeper/app_config.go @@ -20,6 +20,7 @@ var AppConfig = configurator.NewAppConfig( configurator.VestingModule(), configurator.StakingModule(), configurator.TxModule(), + configurator.ValidateModule(), configurator.ConsensusModule(), configurator.GenutilModule(), ) diff --git a/tests/e2e/auth/suite.go b/tests/e2e/auth/suite.go index 544fef1683b4..31dca150f87e 100644 --- a/tests/e2e/auth/suite.go +++ b/tests/e2e/auth/suite.go @@ -357,7 +357,6 @@ func (s *E2ETestSuite) TestCLIQueryTxCmdByHash() { } for _, tc := range testCases { - tc := tc s.Run(tc.name, func() { cmd := authcli.QueryTxCmd() clientCtx := val.GetClientCtx() @@ -490,7 +489,6 @@ func (s *E2ETestSuite) TestCLIQueryTxCmdByEvents() { } for _, tc := range testCases { - tc := tc s.Run(tc.name, func() { cmd := authcli.QueryTxCmd() clientCtx := val.GetClientCtx() @@ -570,7 +568,6 @@ func (s *E2ETestSuite) TestCLIQueryTxsCmdByEvents() { } for _, tc := range testCases { - tc := tc s.Run(tc.name, func() { cmd := authcli.QueryTxsByEventsCmd() clientCtx := val.GetClientCtx() @@ -1503,7 +1500,6 @@ func (s *E2ETestSuite) TestAuxSigner() { } for _, tc := range testCases { - tc := tc s.Run(tc.name, func() { _, err := govtestutil.MsgSubmitLegacyProposal( val.GetClientCtx(), @@ -1730,7 +1726,6 @@ func (s *E2ETestSuite) TestAuxToFeeWithTips() { } for _, tc := range testCases { - tc := tc s.Run(tc.name, func() { res, err := govtestutil.MsgSubmitLegacyProposal( val.GetClientCtx(), diff --git a/tests/e2e/authz/cli_test.go b/tests/e2e/authz/cli_test.go deleted file mode 100644 index 55348c99bd8f..000000000000 --- a/tests/e2e/authz/cli_test.go +++ /dev/null @@ -1,20 +0,0 @@ -//go:build e2e -// +build e2e - -package authz - -import ( - "testing" - - "github.com/stretchr/testify/suite" - - "cosmossdk.io/simapp" - - "github.com/cosmos/cosmos-sdk/testutil/network" -) - -func TestE2ETestSuite(t *testing.T) { - cfg := network.DefaultConfig(simapp.NewTestNetworkFixture) - cfg.NumValidators = 1 - suite.Run(t, NewE2ETestSuite(cfg)) -} diff --git a/tests/e2e/authz/grpc.go b/tests/e2e/authz/grpc.go deleted file mode 100644 index e8b9c3487e25..000000000000 --- a/tests/e2e/authz/grpc.go +++ /dev/null @@ -1,272 +0,0 @@ -package authz - -import ( - "fmt" - "time" - - "cosmossdk.io/math" - "cosmossdk.io/x/authz" - "cosmossdk.io/x/authz/client/cli" - authzclitestutil "cosmossdk.io/x/authz/client/testutil" - banktypes "cosmossdk.io/x/bank/types" - - "github.com/cosmos/cosmos-sdk/client/flags" - "github.com/cosmos/cosmos-sdk/testutil" - sdk "github.com/cosmos/cosmos-sdk/types" -) - -func (s *E2ETestSuite) TestQueryGrantGRPC() { - val := s.network.GetValidators()[0] - grantee := s.grantee[1] - grantsURL := val.GetAPIAddress() + "/cosmos/authz/v1beta1/grants?granter=%s&grantee=%s&msg_type_url=%s" - testCases := []struct { - name string - url string - expectErr bool - errorMsg string - }{ - { - "fail invalid granter address", - fmt.Sprintf(grantsURL, "invalid_granter", grantee.String(), typeMsgSend), - true, - "decoding bech32 failed: invalid separator index -1: invalid request", - }, - { - "fail invalid grantee address", - fmt.Sprintf(grantsURL, val.GetAddress().String(), "invalid_grantee", typeMsgSend), - true, - "decoding bech32 failed: invalid separator index -1: invalid request", - }, - { - "fail with empty granter", - fmt.Sprintf(grantsURL, "", grantee.String(), typeMsgSend), - true, - "empty address string is not allowed: invalid request", - }, - { - "fail with empty grantee", - fmt.Sprintf(grantsURL, val.GetAddress().String(), "", typeMsgSend), - true, - "empty address string is not allowed: invalid request", - }, - { - "fail invalid msg-type", - fmt.Sprintf(grantsURL, val.GetAddress().String(), grantee.String(), "invalidMsg"), - true, - "authorization not found for invalidMsg type", - }, - { - "valid query", - fmt.Sprintf(grantsURL, val.GetAddress().String(), grantee.String(), typeMsgSend), - false, - "", - }, - } - for _, tc := range testCases { - tc := tc - s.Run(tc.name, func() { - resp, _ := testutil.GetRequest(tc.url) - require := s.Require() - if tc.expectErr { - require.Contains(string(resp), tc.errorMsg) - } else { - var g authz.QueryGrantsResponse - err := val.GetClientCtx().Codec.UnmarshalJSON(resp, &g) - require.NoError(err) - require.Len(g.Grants, 1) - err = g.Grants[0].UnpackInterfaces(val.GetClientCtx().InterfaceRegistry) - require.NoError(err) - auth, err := g.Grants[0].GetAuthorization() - require.NoError(err) - require.Equal(auth.MsgTypeURL(), banktypes.SendAuthorization{}.MsgTypeURL()) - } - }) - } -} - -func (s *E2ETestSuite) TestQueryGrantsGRPC() { - val := s.network.GetValidators()[0] - grantee := s.grantee[1] - grantsURL := val.GetAPIAddress() + "/cosmos/authz/v1beta1/grants?granter=%s&grantee=%s" - testCases := []struct { - name string - url string - expectErr bool - errMsg string - preRun func() - postRun func(*authz.QueryGrantsResponse) - }{ - { - "valid query: expect single grant", - fmt.Sprintf(grantsURL, val.GetAddress().String(), grantee.String()), - false, - "", - func() {}, - func(g *authz.QueryGrantsResponse) { - s.Require().Len(g.Grants, 1) - }, - }, - { - "valid query: expect two grants", - fmt.Sprintf(grantsURL, val.GetAddress().String(), grantee.String()), - false, - "", - func() { - _, err := authzclitestutil.CreateGrant(val.GetClientCtx(), []string{ - grantee.String(), - "generic", - fmt.Sprintf("--%s=%s", flags.FlagFrom, val.GetAddress().String()), - fmt.Sprintf("--%s=%s", cli.FlagMsgType, typeMsgVote), - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, math.NewInt(10))).String()), - fmt.Sprintf("--%s=%d", cli.FlagExpiration, time.Now().Add(time.Minute*time.Duration(120)).Unix()), - }) - s.Require().NoError(err) - s.Require().NoError(s.network.WaitForNextBlock()) - }, - func(g *authz.QueryGrantsResponse) { - s.Require().Len(g.Grants, 2) - }, - }, - { - "valid query: expect single grant with pagination", - fmt.Sprintf(grantsURL+"&pagination.limit=1", val.GetAddress().String(), grantee.String()), - false, - "", - func() {}, - func(g *authz.QueryGrantsResponse) { - s.Require().Len(g.Grants, 1) - }, - }, - { - "valid query: expect two grants with pagination", - fmt.Sprintf(grantsURL+"&pagination.limit=2", val.GetAddress().String(), grantee.String()), - false, - "", - func() {}, - func(g *authz.QueryGrantsResponse) { - s.Require().Len(g.Grants, 2) - }, - }, - } - for _, tc := range testCases { - tc := tc - s.Run(tc.name, func() { - tc.preRun() - resp, err := testutil.GetRequest(tc.url) - s.Require().NoError(err) - - if tc.expectErr { - s.Require().Contains(string(resp), tc.errMsg) - } else { - var authorizations authz.QueryGrantsResponse - err := val.GetClientCtx().Codec.UnmarshalJSON(resp, &authorizations) - s.Require().NoError(err) - tc.postRun(&authorizations) - } - }) - } -} - -func (s *E2ETestSuite) TestQueryGranterGrantsGRPC() { - val := s.network.GetValidators()[0] - grantee := s.grantee[1] - require := s.Require() - - testCases := []struct { - name string - url string - expectErr bool - errMsg string - numItems int - }{ - { - "invalid account address", - fmt.Sprintf("%s/cosmos/authz/v1beta1/grants/granter/%s", val.GetAPIAddress(), "invalid address"), - true, - "decoding bech32 failed", - 0, - }, - { - "no authorizations found", - fmt.Sprintf("%s/cosmos/authz/v1beta1/grants/granter/%s", val.GetAPIAddress(), grantee.String()), - false, - "", - 0, - }, - { - "valid query", - fmt.Sprintf("%s/cosmos/authz/v1beta1/grants/granter/%s", val.GetAPIAddress(), val.GetAddress().String()), - false, - "", - 6, - }, - } - for _, tc := range testCases { - s.Run(tc.name, func() { - resp, err := testutil.GetRequest(tc.url) - require.NoError(err) - - if tc.expectErr { - require.Contains(string(resp), tc.errMsg) - } else { - var authorizations authz.QueryGranterGrantsResponse - err := val.GetClientCtx().Codec.UnmarshalJSON(resp, &authorizations) - require.NoError(err) - require.Len(authorizations.Grants, tc.numItems) - } - }) - } -} - -func (s *E2ETestSuite) TestQueryGranteeGrantsGRPC() { - val := s.network.GetValidators()[0] - grantee := s.grantee[1] - require := s.Require() - - testCases := []struct { - name string - url string - expectErr bool - errMsg string - numItems int - }{ - { - "invalid account address", - fmt.Sprintf("%s/cosmos/authz/v1beta1/grants/grantee/%s", val.GetAPIAddress(), "invalid address"), - true, - "decoding bech32 failed", - 0, - }, - { - "no authorizations found", - fmt.Sprintf("%s/cosmos/authz/v1beta1/grants/grantee/%s", val.GetAPIAddress(), val.GetAddress().String()), - false, - "", - 0, - }, - { - "valid query", - fmt.Sprintf("%s/cosmos/authz/v1beta1/grants/grantee/%s", val.GetAPIAddress(), grantee.String()), - false, - "", - 1, - }, - } - for _, tc := range testCases { - s.Run(tc.name, func() { - resp, err := testutil.GetRequest(tc.url) - require.NoError(err) - - if tc.expectErr { - require.Contains(string(resp), tc.errMsg) - } else { - var authorizations authz.QueryGranteeGrantsResponse - err := val.GetClientCtx().Codec.UnmarshalJSON(resp, &authorizations) - require.NoError(err) - require.Len(authorizations.Grants, tc.numItems) - } - }) - } -} diff --git a/tests/e2e/authz/tx.go b/tests/e2e/authz/tx.go deleted file mode 100644 index 811cdf51ded5..000000000000 --- a/tests/e2e/authz/tx.go +++ /dev/null @@ -1,929 +0,0 @@ -package authz - -import ( - "fmt" - "time" - - "github.com/cosmos/gogoproto/proto" - "github.com/stretchr/testify/suite" - - // without this import amino json encoding will fail when resolving any types - _ "cosmossdk.io/api/cosmos/authz/v1beta1" - "cosmossdk.io/math" - "cosmossdk.io/x/authz" - "cosmossdk.io/x/authz/client/cli" - authzclitestutil "cosmossdk.io/x/authz/client/testutil" - bank "cosmossdk.io/x/bank/types" - govcli "cosmossdk.io/x/gov/client/cli" - govtestutil "cosmossdk.io/x/gov/client/testutil" - govv1 "cosmossdk.io/x/gov/types/v1" - govv1beta1 "cosmossdk.io/x/gov/types/v1beta1" - stakingtypes "cosmossdk.io/x/staking/types" - - "github.com/cosmos/cosmos-sdk/client/flags" - "github.com/cosmos/cosmos-sdk/crypto/hd" - "github.com/cosmos/cosmos-sdk/crypto/keyring" - "github.com/cosmos/cosmos-sdk/testutil" - clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli" - "github.com/cosmos/cosmos-sdk/testutil/network" - sdk "github.com/cosmos/cosmos-sdk/types" - authcli "github.com/cosmos/cosmos-sdk/x/auth/client/cli" -) - -type E2ETestSuite struct { - suite.Suite - - cfg network.Config - network network.NetworkI - grantee []sdk.AccAddress -} - -func NewE2ETestSuite(cfg network.Config) *E2ETestSuite { - return &E2ETestSuite{cfg: cfg} -} - -func (s *E2ETestSuite) SetupSuite() { - s.T().Log("setting up e2e test suite") - - var err error - s.network, err = network.New(s.T(), s.T().TempDir(), s.cfg) - s.Require().NoError(err) - - val := s.network.GetValidators()[0] - s.grantee = make([]sdk.AccAddress, 6) - - // Send some funds to the new account. - // Create new account in the keyring. - s.grantee[0] = s.createAccount("grantee1") - s.msgSendExec(s.grantee[0]) - - // create a proposal with deposit - _, err = govtestutil.MsgSubmitLegacyProposal(val.GetClientCtx(), val.GetAddress().String(), - "Text Proposal 1", "Where is the title!?", govv1beta1.ProposalTypeText, - fmt.Sprintf("--%s=%s", govcli.FlagDeposit, sdk.NewCoin(s.cfg.BondDenom, govv1.DefaultMinDepositTokens).String())) - s.Require().NoError(err) - s.Require().NoError(s.network.WaitForNextBlock()) - - // Create new account in the keyring. - s.grantee[1] = s.createAccount("grantee2") - // Send some funds to the new account. - s.msgSendExec(s.grantee[1]) - - // grant send authorization to grantee2 - out, err := authzclitestutil.CreateGrant(val.GetClientCtx(), []string{ - s.grantee[1].String(), - "send", - fmt.Sprintf("--%s=100stake", cli.FlagSpendLimit), - fmt.Sprintf("--%s=%s", flags.FlagFrom, val.GetAddress().String()), - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, math.NewInt(10))).String()), - fmt.Sprintf("--%s=%d", cli.FlagExpiration, time.Now().Add(time.Minute*time.Duration(120)).Unix()), - }) - s.Require().NoError(err) - s.Require().NoError(s.network.WaitForNextBlock()) - var response sdk.TxResponse - s.Require().NoError(val.GetClientCtx().Codec.UnmarshalJSON(out.Bytes(), &response), out.String()) - s.Require().NoError(clitestutil.CheckTxCode(s.network, val.GetClientCtx(), response.TxHash, 0)) - - // Create new account in the keyring. - s.grantee[2] = s.createAccount("grantee3") - - // grant send authorization to grantee3 - _, err = authzclitestutil.CreateGrant(val.GetClientCtx(), []string{ - s.grantee[2].String(), - "send", - fmt.Sprintf("--%s=100stake", cli.FlagSpendLimit), - fmt.Sprintf("--%s=%s", flags.FlagFrom, val.GetAddress().String()), - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, math.NewInt(10))).String()), - fmt.Sprintf("--%s=%d", cli.FlagExpiration, time.Now().Add(time.Minute*time.Duration(120)).Unix()), - }) - s.Require().NoError(err) - s.Require().NoError(s.network.WaitForNextBlock()) - - // Create new accounts in the keyring. - s.grantee[3] = s.createAccount("grantee4") - s.msgSendExec(s.grantee[3]) - - s.grantee[4] = s.createAccount("grantee5") - s.grantee[5] = s.createAccount("grantee6") - - // grant send authorization with allow list to grantee4 - out, err = authzclitestutil.CreateGrant(val.GetClientCtx(), - []string{ - s.grantee[3].String(), - "send", - fmt.Sprintf("--%s=100stake", cli.FlagSpendLimit), - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagFrom, val.GetAddress().String()), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), - fmt.Sprintf("--%s=%d", cli.FlagExpiration, time.Now().Add(time.Minute*time.Duration(120)).Unix()), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10))).String()), - fmt.Sprintf("--%s=%s", cli.FlagAllowList, s.grantee[4]), - }, - ) - s.Require().NoError(err) - s.Require().NoError(s.network.WaitForNextBlock()) - - s.Require().NoError(val.GetClientCtx().Codec.UnmarshalJSON(out.Bytes(), &response), out.String()) - s.Require().NoError(clitestutil.CheckTxCode(s.network, val.GetClientCtx(), response.TxHash, 0)) -} - -func (s *E2ETestSuite) createAccount(uid string) sdk.AccAddress { - val := s.network.GetValidators()[0] - // Create new account in the keyring. - k, _, err := val.GetClientCtx().Keyring.NewMnemonic(uid, keyring.English, sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, hd.Secp256k1) - s.Require().NoError(err) - - addr, err := k.GetAddress() - s.Require().NoError(err) - - return addr -} - -func (s *E2ETestSuite) msgSendExec(grantee sdk.AccAddress) { - val := s.network.GetValidators()[0] - // Send some funds to the new account. - - from := val.GetAddress() - coins := sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(200))) - msgSend := &bank.MsgSend{ - FromAddress: from.String(), - ToAddress: grantee.String(), - Amount: coins, - } - - out, err := clitestutil.SubmitTestTx( - val.GetClientCtx(), - msgSend, - from, - clitestutil.TestTxConfig{}, - ) - - s.Require().NoError(err) - s.Require().Contains(out.String(), `"code":0`) - s.Require().NoError(s.network.WaitForNextBlock()) -} - -func (s *E2ETestSuite) TearDownSuite() { - s.T().Log("tearing down e2e test suite") - s.network.Cleanup() -} - -var ( - typeMsgSend = bank.SendAuthorization{}.MsgTypeURL() - typeMsgVote = sdk.MsgTypeURL(&govv1.MsgVote{}) -) - -func (s *E2ETestSuite) TestExecAuthorizationWithExpiration() { - val := s.network.GetValidators()[0] - grantee := s.grantee[0] - tenSeconds := time.Now().Add(time.Second * time.Duration(10)).Unix() - - _, err := authzclitestutil.CreateGrant( - val.GetClientCtx(), - []string{ - grantee.String(), - "generic", - fmt.Sprintf("--%s=%s", cli.FlagMsgType, typeMsgVote), - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagFrom, val.GetAddress().String()), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), - fmt.Sprintf("--%s=%d", cli.FlagExpiration, tenSeconds), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10))).String()), - }, - ) - s.Require().NoError(err) - // msg vote - voteTx := fmt.Sprintf(`{"body":{"messages":[{"@type":"/cosmos.gov.v1.MsgVote","proposal_id":"1","voter":"%s","option":"VOTE_OPTION_YES"}],"memo":"","timeout_height":"0","extension_options":[],"non_critical_extension_options":[]},"auth_info":{"signer_infos":[],"fee":{"amount":[],"gas_limit":"200000","payer":"","granter":""}},"signatures":[]}`, val.GetAddress().String()) - execMsg := testutil.WriteToNewTempFile(s.T(), voteTx) - defer execMsg.Close() - - // waiting for authorization to expires - time.Sleep(12 * time.Second) - - cmd := cli.NewCmdExecAuthorization() - clientCtx := val.GetClientCtx() - - out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, []string{ - execMsg.Name(), - fmt.Sprintf("--%s=%s", flags.FlagFrom, grantee.String()), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10))).String()), - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - }) - s.Require().NoError(err) - var response sdk.TxResponse - s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &response), out.String()) - s.Require().NoError(clitestutil.CheckTxCode(s.network, clientCtx, response.TxHash, authz.ErrNoAuthorizationFound.ABCICode())) -} - -func (s *E2ETestSuite) TestNewExecGenericAuthorized() { - val := s.network.GetValidators()[0] - grantee := s.grantee[0] - twoHours := time.Now().Add(time.Minute * time.Duration(120)).Unix() - - _, err := authzclitestutil.CreateGrant( - val.GetClientCtx(), - []string{ - grantee.String(), - "generic", - fmt.Sprintf("--%s=%s", cli.FlagMsgType, typeMsgVote), - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagFrom, val.GetAddress().String()), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), - fmt.Sprintf("--%s=%d", cli.FlagExpiration, twoHours), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10))).String()), - }, - ) - s.Require().NoError(err) - s.Require().NoError(s.network.WaitForNextBlock()) - - // msg vote - voteTx := fmt.Sprintf(`{"body":{"messages":[{"@type":"/cosmos.gov.v1.MsgVote","proposal_id":"1","voter":"%s","option":"VOTE_OPTION_YES"}],"memo":"","timeout_height":"0","extension_options":[],"non_critical_extension_options":[]},"auth_info":{"signer_infos":[],"fee":{"amount":[],"gas_limit":"200000","payer":"","granter":""}},"signatures":[]}`, val.GetAddress().String()) - execMsg := testutil.WriteToNewTempFile(s.T(), voteTx) - defer execMsg.Close() - - testCases := []struct { - name string - args []string - respType proto.Message - expectedCode uint32 - expectErr bool - }{ - { - "fail invalid grantee", - []string{ - execMsg.Name(), - fmt.Sprintf("--%s=%s", flags.FlagFrom, "grantee"), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), - fmt.Sprintf("--%s=true", flags.FlagGenerateOnly), - }, - nil, - 0, - true, - }, - { - "fail invalid json path", - []string{ - "/invalid/file.txt", - fmt.Sprintf("--%s=%s", flags.FlagFrom, grantee.String()), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), - }, - nil, - 0, - true, - }, - { - "valid txn", - []string{ - execMsg.Name(), - fmt.Sprintf("--%s=%s", flags.FlagFrom, grantee.String()), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10))).String()), - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - }, - &sdk.TxResponse{}, - 0, - false, - }, - { - "valid tx with amino", - []string{ - execMsg.Name(), - fmt.Sprintf("--%s=%s", flags.FlagFrom, grantee.String()), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10))).String()), - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagSignMode, flags.SignModeLegacyAminoJSON), - }, - &sdk.TxResponse{}, 0, - false, - }, - } - - for _, tc := range testCases { - tc := tc - s.Run(tc.name, func() { - cmd := cli.NewCmdExecAuthorization() - clientCtx := val.GetClientCtx() - - out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) - if tc.expectErr { - s.Require().Error(err) - } else { - s.Require().NoError(err) - s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), tc.respType), out.String()) - txResp := tc.respType.(*sdk.TxResponse) - s.Require().NoError(clitestutil.CheckTxCode(s.network, val.GetClientCtx(), txResp.TxHash, tc.expectedCode)) - } - }) - } -} - -func (s *E2ETestSuite) TestNewExecGrantAuthorized() { - val := s.network.GetValidators()[0] - grantee := s.grantee[0] - grantee1 := s.grantee[2] - twoHours := time.Now().Add(time.Minute * time.Duration(120)).Unix() - - _, err := authzclitestutil.CreateGrant( - val.GetClientCtx(), - []string{ - grantee.String(), - "send", - fmt.Sprintf("--%s=12%stoken", cli.FlagSpendLimit, val.GetMoniker()), - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagFrom, val.GetAddress().String()), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), - fmt.Sprintf("--%s=%d", cli.FlagExpiration, twoHours), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10))).String()), - }, - ) - s.Require().NoError(err) - s.Require().NoError(s.network.WaitForNextBlock()) - - from := val.GetAddress() - tokens := sdk.NewCoins( - sdk.NewCoin(fmt.Sprintf("%stoken", val.GetMoniker()), math.NewInt(12)), - ) - msgSend := &bank.MsgSend{ - FromAddress: from.String(), - ToAddress: grantee.String(), - Amount: tokens, - } - normalGeneratedTx, err := clitestutil.SubmitTestTx( - val.GetClientCtx(), - msgSend, - from, - clitestutil.TestTxConfig{ - GenOnly: true, - }, - ) - - s.Require().NoError(err) - execMsg := testutil.WriteToNewTempFile(s.T(), normalGeneratedTx.String()) - defer execMsg.Close() - testCases := []struct { - name string - args []string - expectedCode uint32 - expectErr bool - expectErrMsg string - }{ - { - "valid txn", - []string{ - execMsg.Name(), - fmt.Sprintf("--%s=%s", flags.FlagFrom, grantee.String()), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10))).String()), - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - }, - 0, - false, - "", - }, - { - "error over grantee doesn't exist on chain", - []string{ - execMsg.Name(), - fmt.Sprintf("--%s=%s", flags.FlagFrom, grantee1.String()), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10))).String()), - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - }, - 0, - true, - "insufficient funds", // earlier the error was account not found here. - }, - { - "error over spent", - []string{ - execMsg.Name(), - fmt.Sprintf("--%s=%s", flags.FlagFrom, grantee.String()), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10))).String()), - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - }, - authz.ErrNoAuthorizationFound.ABCICode(), - false, - "", - }, - } - - for _, tc := range testCases { - tc := tc - s.Run(tc.name, func() { - cmd := cli.NewCmdExecAuthorization() - clientCtx := val.GetClientCtx() - - var response sdk.TxResponse - out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) - switch { - case tc.expectErrMsg != "": - s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &response), out.String()) - s.Require().Contains(response.RawLog, tc.expectErrMsg) - - case tc.expectErr: - s.Require().Error(err) - - default: - s.Require().NoError(err) - s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &response), out.String()) - s.Require().NoError(clitestutil.CheckTxCode(s.network, val.GetClientCtx(), response.TxHash, tc.expectedCode)) - } - }) - } -} - -func (s *E2ETestSuite) TestExecSendAuthzWithAllowList() { - val := s.network.GetValidators()[0] - grantee := s.grantee[3] - allowedAddr := s.grantee[4] - notAllowedAddr := s.grantee[5] - twoHours := time.Now().Add(time.Minute * time.Duration(120)).Unix() - - _, err := authzclitestutil.CreateGrant( - val.GetClientCtx(), - []string{ - grantee.String(), - "send", - fmt.Sprintf("--%s=100stake", cli.FlagSpendLimit), - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagFrom, val.GetAddress().String()), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), - fmt.Sprintf("--%s=%d", cli.FlagExpiration, twoHours), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10))).String()), - fmt.Sprintf("--%s=%s", cli.FlagAllowList, allowedAddr), - }, - ) - s.Require().NoError(err) - s.Require().NoError(s.network.WaitForNextBlock()) - - from := val.GetAddress() - tokens := sdk.NewCoins( - sdk.NewCoin("stake", math.NewInt(12)), - ) - msgSend := &bank.MsgSend{ - FromAddress: from.String(), - ToAddress: allowedAddr.String(), - Amount: tokens, - } - - validGeneratedTx, err := clitestutil.SubmitTestTx( - val.GetClientCtx(), - msgSend, - from, - clitestutil.TestTxConfig{ - GenOnly: true, - }, - ) - s.Require().NoError(err) - execMsg := testutil.WriteToNewTempFile(s.T(), validGeneratedTx.String()) - defer execMsg.Close() - - msgSend1 := &bank.MsgSend{ - FromAddress: from.String(), - ToAddress: notAllowedAddr.String(), - Amount: tokens, - } - invalidGeneratedTx, err := clitestutil.SubmitTestTx( - val.GetClientCtx(), - msgSend1, - from, - clitestutil.TestTxConfig{ - GenOnly: true, - }, - ) - s.Require().NoError(err) - execMsg1 := testutil.WriteToNewTempFile(s.T(), invalidGeneratedTx.String()) - defer execMsg1.Close() - - // test sending to allowed address - args := []string{ - execMsg.Name(), - fmt.Sprintf("--%s=%s", flags.FlagFrom, grantee.String()), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10))).String()), - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - } - var response sdk.TxResponse - cmd := cli.NewCmdExecAuthorization() - out, err := clitestutil.ExecTestCLICmd(val.GetClientCtx(), cmd, args) - s.Require().NoError(err) - s.Require().NoError(val.GetClientCtx().Codec.UnmarshalJSON(out.Bytes(), &response), out.String()) - s.Require().NoError(s.network.WaitForNextBlock()) - - // test sending to not allowed address - args = []string{ - execMsg1.Name(), - fmt.Sprintf("--%s=%s", flags.FlagFrom, grantee.String()), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10))).String()), - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - } - out, err = clitestutil.ExecTestCLICmd(val.GetClientCtx(), cmd, args) - s.Require().NoError(err) - s.Require().NoError(val.GetClientCtx().Codec.UnmarshalJSON(out.Bytes(), &response), out.String()) - s.Require().NoError(s.network.WaitForNextBlock()) - - // query tx and check result - err = s.network.RetryForBlocks(func() error { - out, err = clitestutil.ExecTestCLICmd(val.GetClientCtx(), authcli.QueryTxCmd(), []string{response.TxHash, fmt.Sprintf("--%s=json", flags.FlagOutput)}) - return err - }, 3) - s.Require().NoError(err) - s.Contains(out.String(), fmt.Sprintf("cannot send to %s address", notAllowedAddr)) -} - -func (s *E2ETestSuite) TestExecDelegateAuthorization() { - val := s.network.GetValidators()[0] - grantee := s.grantee[0] - twoHours := time.Now().Add(time.Minute * time.Duration(120)).Unix() - - _, err := authzclitestutil.CreateGrant( - val.GetClientCtx(), - []string{ - grantee.String(), - "delegate", - fmt.Sprintf("--%s=100stake", cli.FlagSpendLimit), - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagFrom, val.GetAddress().String()), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), - fmt.Sprintf("--%s=%d", cli.FlagExpiration, twoHours), - fmt.Sprintf("--%s=%s", cli.FlagAllowedValidators, val.GetValAddress().String()), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10))).String()), - }, - ) - s.Require().NoError(err) - s.Require().NoError(s.network.WaitForNextBlock()) - - tokens := sdk.NewCoins( - sdk.NewCoin("stake", math.NewInt(50)), - ) - - delegateTx := fmt.Sprintf(`{"body":{"messages":[{"@type":"/cosmos.staking.v1beta1.MsgDelegate","delegator_address":"%s","validator_address":"%s","amount":{"denom":"%s","amount":"%s"}}],"memo":"","timeout_height":"0","extension_options":[],"non_critical_extension_options":[]},"auth_info":{"signer_infos":[],"fee":{"amount":[],"gas_limit":"200000","payer":"","granter":""}},"signatures":[]}`, val.GetAddress().String(), val.GetValAddress().String(), - tokens.GetDenomByIndex(0), tokens[0].Amount) - execMsg := testutil.WriteToNewTempFile(s.T(), delegateTx) - defer execMsg.Close() - - testCases := []struct { - name string - args []string - expectedCode uint32 - expectErr bool - errMsg string - }{ - { - "valid txn: (delegate half tokens)", - []string{ - execMsg.Name(), - fmt.Sprintf("--%s=%s", flags.FlagFrom, grantee.String()), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10))).String()), - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - }, - 0, - false, - "", - }, - { - "valid txn: (delegate remaining half tokens)", - []string{ - execMsg.Name(), - fmt.Sprintf("--%s=%s", flags.FlagFrom, grantee.String()), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10))).String()), - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - }, - 0, - false, - "", - }, - { - "failed with error no authorization found", - []string{ - execMsg.Name(), - fmt.Sprintf("--%s=%s", flags.FlagFrom, grantee.String()), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10))).String()), - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - }, - authz.ErrNoAuthorizationFound.ABCICode(), - false, - authz.ErrNoAuthorizationFound.Error(), - }, - } - - for _, tc := range testCases { - tc := tc - s.Run(tc.name, func() { - cmd := cli.NewCmdExecAuthorization() - clientCtx := val.GetClientCtx() - - out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) - if tc.expectErr { - s.Require().Error(err) - s.Require().Contains(err.Error(), tc.errMsg) - } else { - var response sdk.TxResponse - s.Require().NoError(err) - s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &response), out.String()) - s.Require().NoError(clitestutil.CheckTxCode(s.network, val.GetClientCtx(), response.TxHash, tc.expectedCode)) - } - }) - } - - // test delegate no spend-limit - _, err = authzclitestutil.CreateGrant( - val.GetClientCtx(), - []string{ - grantee.String(), - "delegate", - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagFrom, val.GetAddress().String()), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), - fmt.Sprintf("--%s=%d", cli.FlagExpiration, twoHours), - fmt.Sprintf("--%s=%s", cli.FlagAllowedValidators, val.GetValAddress().String()), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10))).String()), - }, - ) - s.Require().NoError(err) - s.Require().NoError(s.network.WaitForNextBlock()) - - tokens = sdk.NewCoins( - sdk.NewCoin("stake", math.NewInt(50)), - ) - - delegateTx = fmt.Sprintf(`{"body":{"messages":[{"@type":"/cosmos.staking.v1beta1.MsgDelegate","delegator_address":"%s","validator_address":"%s","amount":{"denom":"%s","amount":"%s"}}],"memo":"","timeout_height":"0","extension_options":[],"non_critical_extension_options":[]},"auth_info":{"signer_infos":[],"fee":{"amount":[],"gas_limit":"200000","payer":"","granter":""}},"signatures":[]}`, val.GetAddress().String(), val.GetValAddress().String(), - tokens.GetDenomByIndex(0), tokens[0].Amount) - execMsg = testutil.WriteToNewTempFile(s.T(), delegateTx) - defer execMsg.Close() - - testCases = []struct { - name string - args []string - expectedCode uint32 - expectErr bool - errMsg string - }{ - { - "valid txn", - []string{ - execMsg.Name(), - fmt.Sprintf("--%s=%s", flags.FlagFrom, grantee.String()), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10))).String()), - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - }, - 0, - false, - "", - }, - } - - for _, tc := range testCases { - tc := tc - s.Run(tc.name, func() { - cmd := cli.NewCmdExecAuthorization() - clientCtx := val.GetClientCtx() - - out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) - if tc.expectErr { - s.Require().Error(err) - s.Require().Contains(err.Error(), tc.errMsg) - } else { - var response sdk.TxResponse - s.Require().NoError(err) - s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &response), out.String()) - s.Require().NoError(clitestutil.CheckTxCode(s.network, val.GetClientCtx(), response.TxHash, tc.expectedCode)) - } - }) - } - - // test delegating to denied validator - _, err = authzclitestutil.CreateGrant( - val.GetClientCtx(), - []string{ - grantee.String(), - "delegate", - fmt.Sprintf("--%s=100stake", cli.FlagSpendLimit), - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagFrom, val.GetAddress().String()), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), - fmt.Sprintf("--%s=%d", cli.FlagExpiration, twoHours), - fmt.Sprintf("--%s=%s", cli.FlagDenyValidators, val.GetValAddress().String()), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10))).String()), - }, - ) - s.Require().NoError(err) - s.Require().NoError(s.network.WaitForNextBlock()) - - args := []string{ - execMsg.Name(), - fmt.Sprintf("--%s=%s", flags.FlagFrom, grantee.String()), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10))).String()), - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - } - cmd := cli.NewCmdExecAuthorization() - out, err := clitestutil.ExecTestCLICmd(val.GetClientCtx(), cmd, args) - s.Require().NoError(err) - s.Require().NoError(s.network.WaitForNextBlock()) - - var response sdk.TxResponse - s.Require().NoError(val.GetClientCtx().Codec.UnmarshalJSON(out.Bytes(), &response), out.String()) - - // query tx and check result - err = s.network.RetryForBlocks(func() error { - out, err = clitestutil.ExecTestCLICmd(val.GetClientCtx(), authcli.QueryTxCmd(), []string{response.TxHash, fmt.Sprintf("--%s=json", flags.FlagOutput)}) - return err - }, 3) - s.Require().NoError(err) - s.Contains(out.String(), fmt.Sprintf("cannot delegate/undelegate to %s validator", val.GetValAddress().String())) -} - -func (s *E2ETestSuite) TestExecUndelegateAuthorization() { - val := s.network.GetValidators()[0] - grantee := s.grantee[0] - twoHours := time.Now().Add(time.Minute * time.Duration(120)).Unix() - - // granting undelegate msg authorization - _, err := authzclitestutil.CreateGrant( - val.GetClientCtx(), - []string{ - grantee.String(), - "unbond", - fmt.Sprintf("--%s=100stake", cli.FlagSpendLimit), - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagFrom, val.GetAddress().String()), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), - fmt.Sprintf("--%s=%d", cli.FlagExpiration, twoHours), - fmt.Sprintf("--%s=%s", cli.FlagAllowedValidators, val.GetValAddress().String()), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10))).String()), - }, - ) - s.Require().NoError(err) - s.Require().NoError(s.network.WaitForNextBlock()) - - // delegating stakes to validator - msg := &stakingtypes.MsgDelegate{ - DelegatorAddress: val.GetAddress().String(), - ValidatorAddress: val.GetValAddress().String(), - Amount: sdk.NewCoin("stake", math.NewInt(100)), - } - - _, err = clitestutil.SubmitTestTx(val.GetClientCtx(), msg, val.GetAddress(), clitestutil.TestTxConfig{}) - - s.Require().NoError(err) - - tokens := sdk.NewCoins( - sdk.NewCoin("stake", math.NewInt(50)), - ) - - undelegateTx := fmt.Sprintf(`{"body":{"messages":[{"@type":"/cosmos.staking.v1beta1.MsgUndelegate","delegator_address":"%s","validator_address":"%s","amount":{"denom":"%s","amount":"%s"}}],"memo":"","timeout_height":"0","extension_options":[],"non_critical_extension_options":[]},"auth_info":{"signer_infos":[],"fee":{"amount":[],"gas_limit":"200000","payer":"","granter":""}},"signatures":[]}`, val.GetAddress().String(), val.GetValAddress().String(), - tokens.GetDenomByIndex(0), tokens[0].Amount) - execMsg := testutil.WriteToNewTempFile(s.T(), undelegateTx) - defer execMsg.Close() - - testCases := []struct { - name string - args []string - expectedCode uint32 - expectErr bool - errMsg string - }{ - { - "valid txn: (undelegate half tokens)", - []string{ - execMsg.Name(), - fmt.Sprintf("--%s=%s", flags.FlagGas, "250000"), - fmt.Sprintf("--%s=%s", flags.FlagFrom, grantee.String()), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10))).String()), - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - }, - 0, - false, - "", - }, - { - "valid txn: (undelegate remaining half tokens)", - []string{ - execMsg.Name(), - fmt.Sprintf("--%s=%s", flags.FlagGas, "250000"), - fmt.Sprintf("--%s=%s", flags.FlagFrom, grantee.String()), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10))).String()), - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - }, - 0, - false, - "", - }, - { - "failed with error no authorization found", - []string{ - execMsg.Name(), - fmt.Sprintf("--%s=%s", flags.FlagGas, "250000"), - fmt.Sprintf("--%s=%s", flags.FlagFrom, grantee.String()), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10))).String()), - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - }, - authz.ErrNoAuthorizationFound.ABCICode(), - false, - authz.ErrNoAuthorizationFound.Error(), - }, - } - - for _, tc := range testCases { - tc := tc - s.Run(tc.name, func() { - cmd := cli.NewCmdExecAuthorization() - clientCtx := val.GetClientCtx() - - out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) - if tc.expectErr { - s.Require().Error(err) - s.Require().Contains(err.Error(), tc.errMsg) - } else { - var response sdk.TxResponse - s.Require().NoError(err) - s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &response), out.String()) - s.Require().NoError(clitestutil.CheckTxCode(s.network, val.GetClientCtx(), response.TxHash, tc.expectedCode)) - } - }) - } - - // grant undelegate authorization without limit - _, err = authzclitestutil.CreateGrant( - val.GetClientCtx(), - []string{ - grantee.String(), - "unbond", - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagFrom, val.GetAddress().String()), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), - fmt.Sprintf("--%s=%d", cli.FlagExpiration, twoHours), - fmt.Sprintf("--%s=%s", cli.FlagAllowedValidators, val.GetValAddress().String()), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10))).String()), - }, - ) - s.Require().NoError(err) - s.Require().NoError(s.network.WaitForNextBlock()) - - tokens = sdk.NewCoins( - sdk.NewCoin("stake", math.NewInt(50)), - ) - - undelegateTx = fmt.Sprintf(`{"body":{"messages":[{"@type":"/cosmos.staking.v1beta1.MsgUndelegate","delegator_address":"%s","validator_address":"%s","amount":{"denom":"%s","amount":"%s"}}],"memo":"","timeout_height":"0","extension_options":[],"non_critical_extension_options":[]},"auth_info":{"signer_infos":[],"fee":{"amount":[],"gas_limit":"200000","payer":"","granter":""}},"signatures":[]}`, val.GetAddress().String(), val.GetValAddress().String(), - tokens.GetDenomByIndex(0), tokens[0].Amount) - execMsg = testutil.WriteToNewTempFile(s.T(), undelegateTx) - defer execMsg.Close() - - testCases = []struct { - name string - args []string - expectedCode uint32 - expectErr bool - errMsg string - }{ - { - "valid txn", - []string{ - execMsg.Name(), - fmt.Sprintf("--%s=%s", flags.FlagGas, "250000"), - fmt.Sprintf("--%s=%s", flags.FlagFrom, grantee.String()), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10))).String()), - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - }, - 0, - false, - "", - }, - } - - for _, tc := range testCases { - tc := tc - s.Run(tc.name, func() { - cmd := cli.NewCmdExecAuthorization() - clientCtx := val.GetClientCtx() - - out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) - if tc.expectErr { - s.Require().Error(err) - s.Require().Contains(err.Error(), tc.errMsg) - } else { - var response sdk.TxResponse - s.Require().NoError(err) - s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &response), out.String()) - s.Require().NoError(clitestutil.CheckTxCode(s.network, val.GetClientCtx(), response.TxHash, tc.expectedCode)) - } - }) - } -} diff --git a/tests/e2e/baseapp/block_gas_test.go b/tests/e2e/baseapp/block_gas_test.go index 3ce100399438..8de527ec5bd5 100644 --- a/tests/e2e/baseapp/block_gas_test.go +++ b/tests/e2e/baseapp/block_gas_test.go @@ -88,6 +88,7 @@ func TestBaseApp_BlockGas(t *testing.T) { configurator.AccountsModule(), configurator.AuthModule(), configurator.TxModule(), + configurator.ValidateModule(), configurator.ConsensusModule(), configurator.BankModule(), configurator.StakingModule(), diff --git a/tests/e2e/client/grpc/cmtservice/service_test.go b/tests/e2e/client/grpc/cmtservice/service_test.go deleted file mode 100644 index a08c77ce4d1c..000000000000 --- a/tests/e2e/client/grpc/cmtservice/service_test.go +++ /dev/null @@ -1,353 +0,0 @@ -//go:build e2e -// +build e2e - -package cmtservice_test - -import ( - "context" - "fmt" - "testing" - - "github.com/stretchr/testify/suite" - - "cosmossdk.io/simapp" - _ "cosmossdk.io/x/gov" - - "github.com/cosmos/cosmos-sdk/client/grpc/cmtservice" - codectypes "github.com/cosmos/cosmos-sdk/codec/types" - cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" - "github.com/cosmos/cosmos-sdk/testutil" - "github.com/cosmos/cosmos-sdk/testutil/network" - qtypes "github.com/cosmos/cosmos-sdk/types/query" - "github.com/cosmos/cosmos-sdk/version" -) - -type E2ETestSuite struct { - suite.Suite - - cfg network.Config - network network.NetworkI - queryClient cmtservice.ServiceClient -} - -func TestE2ETestSuite(t *testing.T) { - suite.Run(t, new(E2ETestSuite)) -} - -func (s *E2ETestSuite) SetupSuite() { - s.T().Log("setting up e2e test suite") - - cfg := network.DefaultConfig(simapp.NewTestNetworkFixture) - cfg.NumValidators = 1 - s.cfg = cfg - - var err error - s.network, err = network.New(s.T(), s.T().TempDir(), s.cfg) - s.Require().NoError(err) - - s.Require().NoError(s.network.WaitForNextBlock()) - - s.queryClient = cmtservice.NewServiceClient(s.network.GetValidators()[0].GetClientCtx()) -} - -func (s *E2ETestSuite) TearDownSuite() { - s.T().Log("tearing down e2e test suite") - s.network.Cleanup() -} - -func (s *E2ETestSuite) TestQueryNodeInfo() { - val := s.network.GetValidators()[0] - - res, err := s.queryClient.GetNodeInfo(context.Background(), &cmtservice.GetNodeInfoRequest{}) - s.Require().NoError(err) - s.Require().Equal(res.ApplicationVersion.AppName, version.NewInfo().AppName) - - restRes, err := testutil.GetRequest(fmt.Sprintf("%s/cosmos/base/tendermint/v1beta1/node_info", val.GetAPIAddress())) - s.Require().NoError(err) - var getInfoRes cmtservice.GetNodeInfoResponse - s.Require().NoError(val.GetClientCtx().Codec.UnmarshalJSON(restRes, &getInfoRes)) - s.Require().Equal(getInfoRes.ApplicationVersion.AppName, version.NewInfo().AppName) -} - -func (s *E2ETestSuite) TestQuerySyncing() { - val := s.network.GetValidators()[0] - - _, err := s.queryClient.GetSyncing(context.Background(), &cmtservice.GetSyncingRequest{}) - s.Require().NoError(err) - - restRes, err := testutil.GetRequest(fmt.Sprintf("%s/cosmos/base/tendermint/v1beta1/syncing", val.GetAPIAddress())) - s.Require().NoError(err) - var syncingRes cmtservice.GetSyncingResponse - s.Require().NoError(val.GetClientCtx().Codec.UnmarshalJSON(restRes, &syncingRes)) -} - -func (s *E2ETestSuite) TestQueryLatestBlock() { - val := s.network.GetValidators()[0] - - _, err := s.queryClient.GetLatestBlock(context.Background(), &cmtservice.GetLatestBlockRequest{}) - s.Require().NoError(err) - - restRes, err := testutil.GetRequest(fmt.Sprintf("%s/cosmos/base/tendermint/v1beta1/blocks/latest", val.GetAPIAddress())) - s.Require().NoError(err) - var blockInfoRes cmtservice.GetLatestBlockResponse - s.Require().NoError(val.GetClientCtx().Codec.UnmarshalJSON(restRes, &blockInfoRes)) - s.Require().Contains(blockInfoRes.SdkBlock.Header.ProposerAddress, "cosmosvalcons") -} - -func (s *E2ETestSuite) TestQueryBlockByHeight() { - val := s.network.GetValidators()[0] - _, err := s.queryClient.GetBlockByHeight(context.Background(), &cmtservice.GetBlockByHeightRequest{Height: 1}) - s.Require().NoError(err) - - restRes, err := testutil.GetRequest(fmt.Sprintf("%s/cosmos/base/tendermint/v1beta1/blocks/%d", val.GetAPIAddress(), 1)) - s.Require().NoError(err) - var blockInfoRes cmtservice.GetBlockByHeightResponse - s.Require().NoError(val.GetClientCtx().Codec.UnmarshalJSON(restRes, &blockInfoRes)) - s.Require().Contains(blockInfoRes.SdkBlock.Header.ProposerAddress, "cosmosvalcons") -} - -func (s *E2ETestSuite) TestQueryLatestValidatorSet() { - val := s.network.GetValidators()[0] - - // nil pagination - res, err := s.queryClient.GetLatestValidatorSet(context.Background(), &cmtservice.GetLatestValidatorSetRequest{ - Pagination: nil, - }) - s.Require().NoError(err) - s.Require().Equal(1, len(res.Validators)) - content, ok := res.Validators[0].PubKey.GetCachedValue().(cryptotypes.PubKey) - s.Require().Equal(true, ok) - s.Require().Equal(content, val.GetPubKey()) - - // with pagination - _, err = s.queryClient.GetLatestValidatorSet(context.Background(), &cmtservice.GetLatestValidatorSetRequest{Pagination: &qtypes.PageRequest{ - Offset: 0, - Limit: 10, - }}) - s.Require().NoError(err) - - // rest request without pagination - _, err = testutil.GetRequest(fmt.Sprintf("%s/cosmos/base/tendermint/v1beta1/validatorsets/latest", val.GetAPIAddress())) - s.Require().NoError(err) - - // rest request with pagination - restRes, err := testutil.GetRequest(fmt.Sprintf("%s/cosmos/base/tendermint/v1beta1/validatorsets/latest?pagination.offset=%d&pagination.limit=%d", val.GetAPIAddress(), 0, 1)) - s.Require().NoError(err) - var validatorSetRes cmtservice.GetLatestValidatorSetResponse - s.Require().NoError(val.GetClientCtx().Codec.UnmarshalJSON(restRes, &validatorSetRes)) - s.Require().Equal(1, len(validatorSetRes.Validators)) - anyPub, err := codectypes.NewAnyWithValue(val.GetPubKey()) - s.Require().NoError(err) - s.Require().Equal(validatorSetRes.Validators[0].PubKey, anyPub) -} - -func (s *E2ETestSuite) TestLatestValidatorSet_GRPC() { - vals := s.network.GetValidators() - testCases := []struct { - name string - req *cmtservice.GetLatestValidatorSetRequest - expErr bool - expErrMsg string - }{ - {"nil request", nil, true, "cannot be nil"}, - {"no pagination", &cmtservice.GetLatestValidatorSetRequest{}, false, ""}, - {"with pagination", &cmtservice.GetLatestValidatorSetRequest{Pagination: &qtypes.PageRequest{Offset: 0, Limit: uint64(len(vals))}}, false, ""}, - } - for _, tc := range testCases { - tc := tc - s.Run(tc.name, func() { - grpcRes, err := s.queryClient.GetLatestValidatorSet(context.Background(), tc.req) - if tc.expErr { - s.Require().Error(err) - s.Require().Contains(err.Error(), tc.expErrMsg) - } else { - s.Require().NoError(err) - s.Require().Len(grpcRes.Validators, len(vals)) - s.Require().Equal(grpcRes.Pagination.Total, uint64(len(vals))) - content, ok := grpcRes.Validators[0].PubKey.GetCachedValue().(cryptotypes.PubKey) - s.Require().Equal(true, ok) - s.Require().Equal(content, vals[0].GetPubKey()) - } - }) - } -} - -func (s *E2ETestSuite) TestLatestValidatorSet_GRPCGateway() { - vals := s.network.GetValidators() - testCases := []struct { - name string - url string - expErr bool - expErrMsg string - }{ - {"no pagination", fmt.Sprintf("%s/cosmos/base/tendermint/v1beta1/validatorsets/latest", vals[0].GetAPIAddress()), false, ""}, - {"pagination invalid fields", fmt.Sprintf("%s/cosmos/base/tendermint/v1beta1/validatorsets/latest?pagination.offset=-1&pagination.limit=-2", vals[0].GetAPIAddress()), true, "strconv.ParseUint"}, - {"with pagination", fmt.Sprintf("%s/cosmos/base/tendermint/v1beta1/validatorsets/latest?pagination.offset=0&pagination.limit=2", vals[0].GetAPIAddress()), false, ""}, - } - for _, tc := range testCases { - tc := tc - s.Run(tc.name, func() { - res, err := testutil.GetRequest(tc.url) - s.Require().NoError(err) - if tc.expErr { - s.Require().Contains(string(res), tc.expErrMsg) - } else { - var result cmtservice.GetLatestValidatorSetResponse - err = vals[0].GetClientCtx().Codec.UnmarshalJSON(res, &result) - s.Require().NoError(err) - s.Require().Equal(uint64(len(vals)), result.Pagination.Total) - anyPub, err := codectypes.NewAnyWithValue(vals[0].GetPubKey()) - s.Require().NoError(err) - s.Require().Equal(result.Validators[0].PubKey, anyPub) - } - }) - } -} - -func (s *E2ETestSuite) TestValidatorSetByHeight_GRPC() { - vals := s.network.GetValidators() - testCases := []struct { - name string - req *cmtservice.GetValidatorSetByHeightRequest - expErr bool - expErrMsg string - }{ - {"nil request", nil, true, "request cannot be nil"}, - {"empty request", &cmtservice.GetValidatorSetByHeightRequest{}, true, "height must be greater than 0"}, - {"no pagination", &cmtservice.GetValidatorSetByHeightRequest{Height: 1}, false, ""}, - {"with pagination", &cmtservice.GetValidatorSetByHeightRequest{Height: 1, Pagination: &qtypes.PageRequest{Offset: 0, Limit: 1}}, false, ""}, - } - for _, tc := range testCases { - tc := tc - s.Run(tc.name, func() { - grpcRes, err := s.queryClient.GetValidatorSetByHeight(context.Background(), tc.req) - if tc.expErr { - s.Require().Error(err) - s.Require().Contains(err.Error(), tc.expErrMsg) - } else { - s.Require().NoError(err) - s.Require().Len(grpcRes.Validators, len(vals)) - s.Require().Equal(grpcRes.Pagination.Total, uint64(len(vals))) - } - }) - } -} - -func (s *E2ETestSuite) TestValidatorSetByHeight_GRPCGateway() { - vals := s.network.GetValidators() - testCases := []struct { - name string - url string - expErr bool - expErrMsg string - }{ - {"invalid height", fmt.Sprintf("%s/cosmos/base/tendermint/v1beta1/validatorsets/%d", vals[0].GetAPIAddress(), -1), true, "height must be greater than 0"}, - {"no pagination", fmt.Sprintf("%s/cosmos/base/tendermint/v1beta1/validatorsets/%d", vals[0].GetAPIAddress(), 1), false, ""}, - {"pagination invalid fields", fmt.Sprintf("%s/cosmos/base/tendermint/v1beta1/validatorsets/%d?pagination.offset=-1&pagination.limit=-2", vals[0].GetAPIAddress(), 1), true, "strconv.ParseUint"}, - {"with pagination", fmt.Sprintf("%s/cosmos/base/tendermint/v1beta1/validatorsets/%d?pagination.offset=0&pagination.limit=2", vals[0].GetAPIAddress(), 1), false, ""}, - } - for _, tc := range testCases { - tc := tc - s.Run(tc.name, func() { - res, err := testutil.GetRequest(tc.url) - s.Require().NoError(err) - if tc.expErr { - s.Require().Contains(string(res), tc.expErrMsg) - } else { - var result cmtservice.GetValidatorSetByHeightResponse - err = vals[0].GetClientCtx().Codec.UnmarshalJSON(res, &result) - s.Require().NoError(err) - s.Require().Equal(uint64(len(vals)), result.Pagination.Total) - } - }) - } -} - -func (s *E2ETestSuite) TestABCIQuery() { - testCases := []struct { - name string - req *cmtservice.ABCIQueryRequest - expectErr bool - expectedCode uint32 - validQuery bool - }{ - { - name: "valid request with proof", - req: &cmtservice.ABCIQueryRequest{ - Path: "/store/gov/key", - Data: []byte{0x03}, - Prove: true, - }, - validQuery: true, - }, - { - name: "valid request without proof", - req: &cmtservice.ABCIQueryRequest{ - Path: "/store/gov/key", - Data: []byte{0x03}, - Prove: false, - }, - validQuery: true, - }, - { - name: "request with invalid path", - req: &cmtservice.ABCIQueryRequest{ - Path: "/foo/bar", - Data: []byte{0x03}, - }, - expectErr: true, - }, - { - name: "request with invalid path recursive", - req: &cmtservice.ABCIQueryRequest{ - Path: "/cosmos.base.tendermint.v1beta1.Service/ABCIQuery", - Data: s.cfg.Codec.MustMarshal(&cmtservice.ABCIQueryRequest{ - Path: "/cosmos.base.tendermint.v1beta1.Service/ABCIQuery", - }), - }, - expectErr: true, - }, - { - name: "request with invalid broadcast tx path", - req: &cmtservice.ABCIQueryRequest{ - Path: "/cosmos.tx.v1beta1.Service/BroadcastTx", - Data: []byte{0x00}, - }, - expectErr: true, - }, - { - name: "request with invalid data", - req: &cmtservice.ABCIQueryRequest{ - Path: "/store/gov/key", - Data: []byte{0x0044, 0x00}, - }, - validQuery: false, - }, - } - - for _, tc := range testCases { - tc := tc - - s.Run(tc.name, func() { - res, err := s.queryClient.ABCIQuery(context.Background(), tc.req) - if tc.expectErr { - s.Require().Error(err) - s.Require().Nil(res) - } else { - s.Require().NoError(err) - s.Require().NotNil(res) - s.Require().Equal(res.Code, tc.expectedCode) - } - - if tc.validQuery { - s.Require().Greater(res.Height, int64(0)) - s.Require().Greater(len(res.Key), 0, "expected non-empty key") - s.Require().Greater(len(res.Value), 0, "expected non-empty value") - } - - if tc.req.Prove { - s.Require().Greater(len(res.ProofOps.Ops), 0, "expected proofs") - } - }) - } -} diff --git a/tests/e2e/distribution/grpc_query_suite.go b/tests/e2e/distribution/grpc_query_suite.go index 4a5a2c3475b8..991567abfb4e 100644 --- a/tests/e2e/distribution/grpc_query_suite.go +++ b/tests/e2e/distribution/grpc_query_suite.go @@ -64,7 +64,7 @@ func (s *GRPCQueryTestSuite) TestQueryParamsGRPC() { } for _, tc := range testCases { - tc := tc + resp, err := sdktestutil.GetRequest(tc.url) s.Run(tc.name, func() { s.Require().NoError(err) @@ -99,7 +99,7 @@ func (s *GRPCQueryTestSuite) TestQueryValidatorDistributionInfoGRPC() { } for _, tc := range testCases { - tc := tc + resp, err := sdktestutil.GetRequest(tc.url) s.Run(tc.name, func() { if tc.expErr { @@ -152,7 +152,7 @@ func (s *GRPCQueryTestSuite) TestQueryOutstandingRewardsGRPC() { } for _, tc := range testCases { - tc := tc + resp, err := sdktestutil.GetRequestWithHeaders(tc.url, tc.headers) s.Run(tc.name, func() { if tc.expErr { @@ -206,7 +206,7 @@ func (s *GRPCQueryTestSuite) TestQueryValidatorCommissionGRPC() { } for _, tc := range testCases { - tc := tc + resp, err := sdktestutil.GetRequestWithHeaders(tc.url, tc.headers) s.Run(tc.name, func() { if tc.expErr { @@ -264,7 +264,7 @@ func (s *GRPCQueryTestSuite) TestQuerySlashesGRPC() { } for _, tc := range testCases { - tc := tc + resp, err := sdktestutil.GetRequest(tc.url) s.Run(tc.name, func() { @@ -340,7 +340,7 @@ func (s *GRPCQueryTestSuite) TestQueryDelegatorRewardsGRPC() { } for _, tc := range testCases { - tc := tc + resp, err := sdktestutil.GetRequestWithHeaders(tc.url, tc.headers) s.Run(tc.name, func() { @@ -392,7 +392,7 @@ func (s *GRPCQueryTestSuite) TestQueryDelegatorValidatorsGRPC() { } for _, tc := range testCases { - tc := tc + resp, err := sdktestutil.GetRequest(tc.url) s.Run(tc.name, func() { @@ -444,7 +444,7 @@ func (s *GRPCQueryTestSuite) TestQueryWithdrawAddressGRPC() { } for _, tc := range testCases { - tc := tc + resp, err := sdktestutil.GetRequest(tc.url) s.Run(tc.name, func() { diff --git a/tests/e2e/gov/cli_test.go b/tests/e2e/gov/cli_test.go deleted file mode 100644 index be8e7afc82e3..000000000000 --- a/tests/e2e/gov/cli_test.go +++ /dev/null @@ -1,37 +0,0 @@ -//go:build e2e -// +build e2e - -package gov - -import ( - "testing" - "time" - - "github.com/stretchr/testify/require" - "github.com/stretchr/testify/suite" - - "cosmossdk.io/simapp" - v1 "cosmossdk.io/x/gov/types/v1" - - "github.com/cosmos/cosmos-sdk/testutil/network" -) - -func TestE2ETestSuite(t *testing.T) { - cfg := network.DefaultConfig(simapp.NewTestNetworkFixture) - cfg.NumValidators = 1 - suite.Run(t, NewE2ETestSuite(cfg)) -} - -func TestDepositTestSuite(t *testing.T) { - cfg := network.DefaultConfig(simapp.NewTestNetworkFixture) - cfg.NumValidators = 1 - genesisState := v1.DefaultGenesisState() - maxDepPeriod := time.Duration(20) * time.Second - votingPeriod := time.Duration(8) * time.Second - genesisState.Params.MaxDepositPeriod = &maxDepPeriod - genesisState.Params.VotingPeriod = &votingPeriod - bz, err := cfg.Codec.MarshalJSON(genesisState) - require.NoError(t, err) - cfg.GenesisState["gov"] = bz - suite.Run(t, NewDepositTestSuite(cfg)) -} diff --git a/tests/e2e/gov/deposits.go b/tests/e2e/gov/deposits.go deleted file mode 100644 index b685fa08bc62..000000000000 --- a/tests/e2e/gov/deposits.go +++ /dev/null @@ -1,164 +0,0 @@ -package gov - -import ( - "fmt" - "strconv" - "time" - - "github.com/stretchr/testify/suite" - - "cosmossdk.io/math" - "cosmossdk.io/x/gov/client/cli" - govclitestutil "cosmossdk.io/x/gov/client/testutil" - v1 "cosmossdk.io/x/gov/types/v1" - "cosmossdk.io/x/gov/types/v1beta1" - - "github.com/cosmos/cosmos-sdk/testutil" - "github.com/cosmos/cosmos-sdk/testutil/network" - sdk "github.com/cosmos/cosmos-sdk/types" -) - -type DepositTestSuite struct { - suite.Suite - - cfg network.Config - network network.NetworkI -} - -func NewDepositTestSuite(cfg network.Config) *DepositTestSuite { - return &DepositTestSuite{cfg: cfg} -} - -func (s *DepositTestSuite) SetupSuite() { - s.T().Log("setting up test suite") - - var err error - s.network, err = network.New(s.T(), s.T().TempDir(), s.cfg) - s.Require().NoError(err) -} - -func (s *DepositTestSuite) submitProposal(val network.ValidatorI, initialDeposit sdk.Coin, name string) uint64 { - var exactArgs []string - - if !initialDeposit.IsZero() { - exactArgs = append(exactArgs, fmt.Sprintf("--%s=%s", cli.FlagDeposit, initialDeposit.String())) - } - - _, err := govclitestutil.MsgSubmitLegacyProposal( - val.GetClientCtx(), - val.GetAddress().String(), - fmt.Sprintf("Text Proposal %s", name), - "Where is the title!?", - v1beta1.ProposalTypeText, - exactArgs..., - ) - s.Require().NoError(err) - s.Require().NoError(s.network.WaitForNextBlock()) - - // query proposals, return the last's id - res, err := testutil.GetRequest(fmt.Sprintf("%s/cosmos/gov/v1/proposals", val.GetAPIAddress())) - s.Require().NoError(err) - var proposals v1.QueryProposalsResponse - err = s.cfg.Codec.UnmarshalJSON(res, &proposals) - s.Require().NoError(err) - s.Require().GreaterOrEqual(len(proposals.Proposals), 1) - - return proposals.Proposals[len(proposals.Proposals)-1].Id -} - -func (s *DepositTestSuite) TearDownSuite() { - s.T().Log("tearing down test suite") - s.network.Cleanup() -} - -func (s *DepositTestSuite) TestQueryDepositsWithInitialDeposit() { - val := s.network.GetValidators()[0] - depositAmount := sdk.NewCoin(s.cfg.BondDenom, v1.DefaultMinDepositTokens) - - // submit proposal with an initial deposit - id := s.submitProposal(val, depositAmount, "TestQueryDepositsWithInitialDeposit") - proposalID := strconv.FormatUint(id, 10) - - // query deposit - deposit := s.queryDeposit(val, proposalID, false, "") - s.Require().NotNil(deposit) - s.Require().Equal(depositAmount.String(), sdk.Coins(deposit.Deposit.Amount).String()) - - // query deposits - deposits := s.queryDeposits(val, proposalID, false, "") - s.Require().NotNil(deposits) - s.Require().Len(deposits.Deposits, 1) - // verify initial deposit - s.Require().Equal(depositAmount.String(), sdk.Coins(deposits.Deposits[0].Amount).String()) -} - -func (s *DepositTestSuite) TestQueryProposalAfterVotingPeriod() { - val := s.network.GetValidators()[0] - depositAmount := sdk.NewCoin(s.cfg.BondDenom, v1.DefaultMinDepositTokens.Sub(math.NewInt(50))) - - // submit proposal with an initial deposit - id := s.submitProposal(val, depositAmount, "TestQueryProposalAfterVotingPeriod") - proposalID := strconv.FormatUint(id, 10) - - resp, err := testutil.GetRequest(fmt.Sprintf("%s/cosmos/gov/v1/proposals", val.GetAPIAddress())) - s.Require().NoError(err) - var proposals v1.QueryProposalsResponse - err = s.cfg.Codec.UnmarshalJSON(resp, &proposals) - s.Require().NoError(err) - s.Require().GreaterOrEqual(len(proposals.Proposals), 1) - - // query proposal - resp, err = testutil.GetRequest(fmt.Sprintf("%s/cosmos/gov/v1/proposals/%s", val.GetAPIAddress(), proposalID)) - s.Require().NoError(err) - var proposal v1.QueryProposalResponse - err = s.cfg.Codec.UnmarshalJSON(resp, &proposal) - s.Require().NoError(err) - - // waiting for deposit and voting period to end - time.Sleep(25 * time.Second) - - // query proposal - resp, err = testutil.GetRequest(fmt.Sprintf("%s/cosmos/gov/v1/proposals/%s", val.GetAPIAddress(), proposalID)) - s.Require().NoError(err) - s.Require().Contains(string(resp), fmt.Sprintf("proposal %s doesn't exist", proposalID)) - - // query deposits - deposits := s.queryDeposits(val, proposalID, false, "") - s.Require().Len(deposits.Deposits, 0) -} - -func (s *DepositTestSuite) queryDeposits(val network.ValidatorI, proposalID string, exceptErr bool, message string) *v1.QueryDepositsResponse { - s.Require().NoError(s.network.WaitForNextBlock()) - - resp, err := testutil.GetRequest(fmt.Sprintf("%s/cosmos/gov/v1/proposals/%s/deposits", val.GetAPIAddress(), proposalID)) - s.Require().NoError(err) - - if exceptErr { - s.Require().Contains(string(resp), message) - return nil - } - - var depositsRes v1.QueryDepositsResponse - err = val.GetClientCtx().Codec.UnmarshalJSON(resp, &depositsRes) - s.Require().NoError(err) - - return &depositsRes -} - -func (s *DepositTestSuite) queryDeposit(val network.ValidatorI, proposalID string, exceptErr bool, message string) *v1.QueryDepositResponse { - s.Require().NoError(s.network.WaitForNextBlock()) - - resp, err := testutil.GetRequest(fmt.Sprintf("%s/cosmos/gov/v1/proposals/%s/deposits/%s", val.GetAPIAddress(), proposalID, val.GetAddress().String())) - s.Require().NoError(err) - - if exceptErr { - s.Require().Contains(string(resp), message) - return nil - } - - var depositRes v1.QueryDepositResponse - err = val.GetClientCtx().Codec.UnmarshalJSON(resp, &depositRes) - s.Require().NoError(err) - - return &depositRes -} diff --git a/tests/e2e/gov/tx.go b/tests/e2e/gov/tx.go deleted file mode 100644 index 3806e54a8823..000000000000 --- a/tests/e2e/gov/tx.go +++ /dev/null @@ -1,377 +0,0 @@ -package gov - -import ( - "encoding/base64" - "fmt" - - "github.com/cosmos/gogoproto/proto" - "github.com/stretchr/testify/suite" - - "cosmossdk.io/math" - "cosmossdk.io/x/gov/client/cli" - govclitestutil "cosmossdk.io/x/gov/client/testutil" - "cosmossdk.io/x/gov/types" - v1 "cosmossdk.io/x/gov/types/v1" - "cosmossdk.io/x/gov/types/v1beta1" - - "github.com/cosmos/cosmos-sdk/client/flags" - "github.com/cosmos/cosmos-sdk/testutil" - clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli" - "github.com/cosmos/cosmos-sdk/testutil/network" - sdk "github.com/cosmos/cosmos-sdk/types" - authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" -) - -type E2ETestSuite struct { - suite.Suite - - cfg network.Config - network network.NetworkI -} - -func NewE2ETestSuite(cfg network.Config) *E2ETestSuite { - return &E2ETestSuite{cfg: cfg} -} - -func (s *E2ETestSuite) SetupSuite() { - s.T().Log("setting up e2e test suite") - - var err error - s.network, err = network.New(s.T(), s.T().TempDir(), s.cfg) - s.Require().NoError(err) - s.Require().NoError(s.network.WaitForNextBlock()) - - val := s.network.GetValidators()[0] - clientCtx := val.GetClientCtx() - var resp sdk.TxResponse - - // create a proposal with deposit - out, err := govclitestutil.MsgSubmitLegacyProposal(val.GetClientCtx(), val.GetAddress().String(), - "Text Proposal 1", "Where is the title!?", v1beta1.ProposalTypeText, - fmt.Sprintf("--%s=%s", cli.FlagDeposit, sdk.NewCoin(s.cfg.BondDenom, v1.DefaultMinDepositTokens).String())) - s.Require().NoError(err) - s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &resp), out.String()) - s.Require().NoError(clitestutil.CheckTxCode(s.network, clientCtx, resp.TxHash, 0)) - - // vote for proposal - out, err = govclitestutil.MsgVote(val.GetClientCtx(), val.GetAddress().String(), "1", "yes") - s.Require().NoError(err) - s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &resp), out.String()) - s.Require().NoError(clitestutil.CheckTxCode(s.network, clientCtx, resp.TxHash, 0)) - - // create a proposal with a small deposit - minimumAcceptedDep := v1.DefaultMinDepositTokens.ToLegacyDec().Mul(v1.DefaultMinDepositRatio).Ceil().TruncateInt() - out, err = govclitestutil.MsgSubmitLegacyProposal(val.GetClientCtx(), val.GetAddress().String(), - "Text Proposal 2", "Where is the title!?", v1beta1.ProposalTypeText, - fmt.Sprintf("--%s=%s", cli.FlagDeposit, sdk.NewCoin(s.cfg.BondDenom, minimumAcceptedDep).String())) - - s.Require().NoError(err) - s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &resp), out.String()) - s.Require().NoError(clitestutil.CheckTxCode(s.network, clientCtx, resp.TxHash, 0)) - - // create a proposal3 with deposit - out, err = govclitestutil.MsgSubmitLegacyProposal(val.GetClientCtx(), val.GetAddress().String(), - "Text Proposal 3", "Where is the title!?", v1beta1.ProposalTypeText, - fmt.Sprintf("--%s=%s", cli.FlagDeposit, sdk.NewCoin(s.cfg.BondDenom, v1.DefaultMinDepositTokens).String())) - s.Require().NoError(err) - s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &resp), out.String()) - s.Require().NoError(clitestutil.CheckTxCode(s.network, clientCtx, resp.TxHash, 0)) - - // create a proposal4 with deposit to check the cancel proposal cli tx - out, err = govclitestutil.MsgSubmitLegacyProposal(val.GetClientCtx(), val.GetAddress().String(), - "Text Proposal 4", "Where is the title!?", v1beta1.ProposalTypeText, - fmt.Sprintf("--%s=%s", cli.FlagDeposit, sdk.NewCoin(s.cfg.BondDenom, v1.DefaultMinDepositTokens).String())) - s.Require().NoError(err) - s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &resp), out.String()) - s.Require().NoError(clitestutil.CheckTxCode(s.network, clientCtx, resp.TxHash, 0)) - - // vote for proposal3 as val - out, err = govclitestutil.MsgVote(val.GetClientCtx(), val.GetAddress().String(), "3", "yes=0.6,no=0.3,abstain=0.05,no_with_veto=0.05") - s.Require().NoError(err) - s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &resp), out.String()) - s.Require().NoError(clitestutil.CheckTxCode(s.network, clientCtx, resp.TxHash, 0)) -} - -func (s *E2ETestSuite) TearDownSuite() { - s.T().Log("tearing down e2e test suite") - s.network.Cleanup() -} - -func (s *E2ETestSuite) TestNewCmdSubmitProposal() { - val := s.network.GetValidators()[0] - - // Create a legacy proposal JSON, make sure it doesn't pass this new CLI - // command. - invalidProp := `{ - "title": "", - "description": "Where is the title!?", - "type": "Text", - "deposit": "-324foocoin" -}` - invalidPropFile := testutil.WriteToNewTempFile(s.T(), invalidProp) - defer invalidPropFile.Close() - - // Create a valid new proposal JSON. - propMetadata := []byte{42} - validProp := fmt.Sprintf(` -{ - "messages": [ - { - "@type": "/cosmos.gov.v1.MsgExecLegacyContent", - "authority": "%s", - "content": { - "@type": "/cosmos.gov.v1beta1.TextProposal", - "title": "My awesome title", - "description": "My awesome description" - } - } - ], - "title": "My awesome title", - "summary": "My awesome description", - "metadata": "%s", - "deposit": "%s" -}`, authtypes.NewModuleAddress(types.ModuleName), base64.StdEncoding.EncodeToString(propMetadata), sdk.NewCoin(s.cfg.BondDenom, math.NewInt(100000))) - validPropFile := testutil.WriteToNewTempFile(s.T(), validProp) - defer validPropFile.Close() - - testCases := []struct { - name string - args []string - expectErr bool - expectedCode uint32 - respType proto.Message - }{ - { - "invalid proposal", - []string{ - invalidPropFile.Name(), - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10))).String()), - }, - true, 0, nil, - }, - { - "valid proposal", - []string{ - validPropFile.Name(), - fmt.Sprintf("--%s=%s", flags.FlagFrom, val.GetAddress().String()), - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10))).String()), - }, - false, 0, &sdk.TxResponse{}, - }, - } - - for _, tc := range testCases { - tc := tc - - s.Run(tc.name, func() { - cmd := cli.NewCmdSubmitProposal() - clientCtx := val.GetClientCtx() - - out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) - if tc.expectErr { - s.Require().Error(err) - } else { - s.Require().NoError(err) - s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), tc.respType), out.String()) - txResp := tc.respType.(*sdk.TxResponse) - s.Require().NoError(clitestutil.CheckTxCode(s.network, clientCtx, txResp.TxHash, tc.expectedCode)) - } - }) - } -} - -func (s *E2ETestSuite) TestNewCmdSubmitLegacyProposal() { - val := s.network.GetValidators()[0] - invalidProp := `{ - "title": "", - "description": "Where is the title!?", - "type": "Text", - "deposit": "-324foocoin" - }` - invalidPropFile := testutil.WriteToNewTempFile(s.T(), invalidProp) - defer invalidPropFile.Close() - validProp := fmt.Sprintf(`{ - "title": "Text Proposal", - "description": "Hello, World!", - "type": "Text", - "deposit": "%s" - }`, sdk.NewCoin(s.cfg.BondDenom, math.NewInt(154310))) - validPropFile := testutil.WriteToNewTempFile(s.T(), validProp) - defer validPropFile.Close() - - testCases := []struct { - name string - args []string - expectErr bool - expectedCode uint32 - respType proto.Message - }{ - { - "invalid proposal (file)", - []string{ - fmt.Sprintf("--%s=%s", cli.FlagProposal, invalidPropFile.Name()), //nolint:staticcheck // we are intentionally using a deprecated flag here. - fmt.Sprintf("--%s=%s", flags.FlagFrom, val.GetAddress().String()), - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10))).String()), - }, - true, 0, nil, - }, - { - "invalid proposal", - []string{ - fmt.Sprintf("--%s='Where is the title!?'", cli.FlagDescription), //nolint:staticcheck // we are intentionally using a deprecated flag here. - fmt.Sprintf("--%s=%s", cli.FlagProposalType, v1beta1.ProposalTypeText), //nolint:staticcheck // we are intentionally using a deprecated flag here. - fmt.Sprintf("--%s=%s", cli.FlagDeposit, sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10000)).String()), - fmt.Sprintf("--%s=%s", flags.FlagFrom, val.GetAddress().String()), - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10))).String()), - }, - true, 0, nil, - }, - { - "valid transaction (file)", - //nolint:staticcheck // we are intentionally using a deprecated flag here. - []string{ - fmt.Sprintf("--%s=%s", cli.FlagProposal, validPropFile.Name()), - fmt.Sprintf("--%s=%s", flags.FlagFrom, val.GetAddress().String()), - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10))).String()), - }, - false, 0, &sdk.TxResponse{}, - }, - { - "valid transaction", - []string{ - fmt.Sprintf("--%s='Text Proposal'", cli.FlagTitle), - fmt.Sprintf("--%s='Where is the title!?'", cli.FlagDescription), //nolint:staticcheck // we are intentionally using a deprecated flag here. - fmt.Sprintf("--%s=%s", cli.FlagProposalType, v1beta1.ProposalTypeText), //nolint:staticcheck // we are intentionally using a deprecated flag here. - fmt.Sprintf("--%s=%s", cli.FlagDeposit, sdk.NewCoin(s.cfg.BondDenom, math.NewInt(100000)).String()), - fmt.Sprintf("--%s=%s", flags.FlagFrom, val.GetAddress().String()), - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10))).String()), - }, - false, 0, &sdk.TxResponse{}, - }, - } - - for _, tc := range testCases { - tc := tc - - s.Run(tc.name, func() { - cmd := cli.NewCmdSubmitLegacyProposal() - clientCtx := val.GetClientCtx() - - out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) - if tc.expectErr { - s.Require().Error(err) - } else { - s.Require().NoError(err) - s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), tc.respType), out.String()) - txResp := tc.respType.(*sdk.TxResponse) - s.Require().NoError(clitestutil.CheckTxCode(s.network, clientCtx, txResp.TxHash, tc.expectedCode)) - } - }) - } -} - -func (s *E2ETestSuite) TestNewCmdWeightedVote() { - val := s.network.GetValidators()[0] - - testCases := []struct { - name string - args []string - expectErr bool - expectedCode uint32 - }{ - { - "invalid vote", - []string{}, - true, 0, - }, - { - "vote for invalid proposal", - []string{ - "10", - "yes", - fmt.Sprintf("--%s=%s", flags.FlagFrom, val.GetAddress().String()), - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10))).String()), - }, - false, 3, - }, - { - "valid vote", - []string{ - "1", - "yes", - fmt.Sprintf("--%s=%s", flags.FlagFrom, val.GetAddress().String()), - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10))).String()), - }, - false, 0, - }, - { - "valid vote with metadata", - []string{ - "1", - "yes", - fmt.Sprintf("--%s=%s", flags.FlagFrom, val.GetAddress().String()), - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), - fmt.Sprintf("--metadata=%s", "AQ=="), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10))).String()), - }, - false, 0, - }, - { - "invalid valid split vote string", - []string{ - "1", - "yes/0.6,no/0.3,abstain/0.05,no_with_veto/0.05", - fmt.Sprintf("--%s=%s", flags.FlagFrom, val.GetAddress().String()), - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10))).String()), - }, - true, 0, - }, - { - "valid split vote", - []string{ - "1", - "yes=0.6,no=0.3,abstain=0.05,no_with_veto=0.05", - fmt.Sprintf("--%s=%s", flags.FlagFrom, val.GetAddress().String()), - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10))).String()), - }, - false, 0, - }, - } - - for _, tc := range testCases { - tc := tc - s.Run(tc.name, func() { - cmd := cli.NewCmdWeightedVote() - clientCtx := val.GetClientCtx() - var txResp sdk.TxResponse - - out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) - - if tc.expectErr { - s.Require().Error(err) - } else { - s.Require().NoError(err) - s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &txResp), out.String()) - s.Require().NoError(clitestutil.CheckTxCode(s.network, clientCtx, txResp.TxHash, tc.expectedCode)) - } - }) - } -} diff --git a/tests/e2e/staking/cli_test.go b/tests/e2e/staking/cli_test.go deleted file mode 100644 index 0705c5645e63..000000000000 --- a/tests/e2e/staking/cli_test.go +++ /dev/null @@ -1,20 +0,0 @@ -//go:build e2e -// +build e2e - -package testutil - -import ( - "testing" - - "github.com/stretchr/testify/suite" - - "cosmossdk.io/simapp" - - "github.com/cosmos/cosmos-sdk/testutil/network" -) - -func TestE2ETestSuite(t *testing.T) { - cfg := network.DefaultConfig(simapp.NewTestNetworkFixture) - cfg.NumValidators = 2 - suite.Run(t, NewE2ETestSuite(cfg)) -} diff --git a/tests/e2e/staking/suite.go b/tests/e2e/staking/suite.go deleted file mode 100644 index 1d08429f3b09..000000000000 --- a/tests/e2e/staking/suite.go +++ /dev/null @@ -1,122 +0,0 @@ -package testutil - -import ( - "context" - "errors" - "testing" - - "github.com/cometbft/cometbft/rpc/client/http" - "github.com/stretchr/testify/suite" - - "cosmossdk.io/math" - banktypes "cosmossdk.io/x/bank/types" - stakingtypes "cosmossdk.io/x/staking/types" - - "github.com/cosmos/cosmos-sdk/crypto/hd" - "github.com/cosmos/cosmos-sdk/crypto/keyring" - clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli" - "github.com/cosmos/cosmos-sdk/testutil/network" - sdk "github.com/cosmos/cosmos-sdk/types" -) - -type E2ETestSuite struct { - suite.Suite - - cfg network.Config - network network.NetworkI -} - -func NewE2ETestSuite(cfg network.Config) *E2ETestSuite { - return &E2ETestSuite{cfg: cfg} -} - -func (s *E2ETestSuite) SetupSuite() { - s.T().Log("setting up e2e test suite") - - if testing.Short() { - s.T().Skip("skipping test in unit-tests mode.") - } - - var err error - s.network, err = network.New(s.T(), s.T().TempDir(), s.cfg) - s.Require().NoError(err) -} - -func (s *E2ETestSuite) TearDownSuite() { - s.T().Log("tearing down e2e test suite") - s.network.Cleanup() -} - -// TestBlockResults tests that the validator updates correctly show when -// calling the /block_results RPC endpoint. -// ref: https://github.com/cosmos/cosmos-sdk/issues/7401. -func (s *E2ETestSuite) TestBlockResults() { - require := s.Require() - val := s.network.GetValidators()[0] - - // Create new account in the keyring. - k, _, err := val.GetClientCtx().Keyring.NewMnemonic("NewDelegator", keyring.English, sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, hd.Secp256k1) - require.NoError(err) - pub, err := k.GetPubKey() - require.NoError(err) - newAddr := sdk.AccAddress(pub.Address()) - - msgSend := &banktypes.MsgSend{ - FromAddress: val.GetAddress().String(), - ToAddress: newAddr.String(), - Amount: sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(200))), - } - - // Send some funds to the new account. - _, err = clitestutil.SubmitTestTx( - val.GetClientCtx(), - msgSend, - val.GetAddress(), - clitestutil.TestTxConfig{}, - ) - require.NoError(err) - require.NoError(s.network.WaitForNextBlock()) - - msgDel := &stakingtypes.MsgDelegate{ - DelegatorAddress: newAddr.String(), - ValidatorAddress: val.GetValAddress().String(), - Amount: sdk.NewCoin(s.cfg.BondDenom, math.NewInt(150)), - } - - // create a delegation from the new account to validator `val`. - _, err = clitestutil.SubmitTestTx( - val.GetClientCtx(), - msgDel, - newAddr, - clitestutil.TestTxConfig{}, - ) - require.NoError(err) - require.NoError(s.network.WaitForNextBlock()) - - // Create a HTTP rpc client. - rpcClient, err := http.New(val.GetRPCAddress()) - require.NoError(err) - - // Loop until we find a block result with the correct validator updates. - // By experience, it happens around 2 blocks after `delHeight`. - _ = s.network.RetryForBlocks(func() error { - latestHeight, err := s.network.LatestHeight() - require.NoError(err) - res, err := rpcClient.BlockResults(context.Background(), &latestHeight) - if err != nil { - return err - } - - if len(res.ValidatorUpdates) == 0 { - return errors.New("validator update not found yet") - } - - valUpdate := res.ValidatorUpdates[0] - require.Equal( - valUpdate.PubKeyBytes, - val.GetPubKey().Bytes(), - ) - - return nil - }, 10) -} diff --git a/tests/e2e/tx/service_test.go b/tests/e2e/tx/service_test.go index b9e875f1173e..f0e4e527664c 100644 --- a/tests/e2e/tx/service_test.go +++ b/tests/e2e/tx/service_test.go @@ -175,7 +175,6 @@ func (s *E2ETestSuite) TestSimulateTx_GRPC() { } for _, tc := range testCases { - tc := tc s.Run(tc.name, func() { // Broadcast the tx via gRPC via the validator's clientCtx (which goes // through Tendermint). @@ -506,7 +505,6 @@ func (s *E2ETestSuite) TestBroadcastTx_GRPC() { } for _, tc := range testCases { - tc := tc s.Run(tc.name, func() { // Broadcast the tx via gRPC via the validator's clientCtx (which goes // through Tendermint). @@ -772,7 +770,6 @@ func (s *E2ETestSuite) TestTxEncode_GRPC() { } for _, tc := range testCases { - tc := tc s.Run(tc.name, func() { res, err := s.queryClient.TxEncode(context.Background(), tc.req) if tc.expErr { @@ -852,7 +849,6 @@ func (s *E2ETestSuite) TestTxDecode_GRPC() { } for _, tc := range testCases { - tc := tc s.Run(tc.name, func() { res, err := s.queryClient.TxDecode(context.Background(), tc.req) if tc.expErr { @@ -963,7 +959,6 @@ func (s *E2ETestSuite) TestTxEncodeAmino_GRPC() { } for _, tc := range testCases { - tc := tc s.Run(tc.name, func() { res, err := s.queryClient.TxEncodeAmino(context.Background(), tc.req) if tc.expErr { @@ -1049,7 +1044,6 @@ func (s *E2ETestSuite) TestTxDecodeAmino_GRPC() { } for _, tc := range testCases { - tc := tc s.Run(tc.name, func() { res, err := s.queryClient.TxDecodeAmino(context.Background(), tc.req) if tc.expErr { diff --git a/tests/go.mod b/tests/go.mod index 9f834034fab6..bbc2a3c3e485 100644 --- a/tests/go.mod +++ b/tests/go.mod @@ -3,22 +3,21 @@ module github.com/cosmos/cosmos-sdk/tests go 1.23.1 require ( - cosmossdk.io/api v0.7.5 + cosmossdk.io/api v0.7.6 cosmossdk.io/collections v0.4.0 - cosmossdk.io/core v1.0.0-alpha.2 + cosmossdk.io/core v1.0.0-alpha.4 cosmossdk.io/depinject v1.0.0 cosmossdk.io/log v1.4.1 cosmossdk.io/math v1.3.0 cosmossdk.io/simapp v0.0.0-20230309163709-87da587416ba - cosmossdk.io/store v1.1.1-0.20240418092142-896cdf1971bc + cosmossdk.io/store v1.1.1 cosmossdk.io/x/evidence v0.0.0-20230613133644-0a778132a60f cosmossdk.io/x/feegrant v0.0.0-20230613133644-0a778132a60f - cosmossdk.io/x/nft v0.0.0-20230613133644-0a778132a60f + cosmossdk.io/x/nft v0.0.0-20230613133644-0a778132a60f // indirect cosmossdk.io/x/protocolpool v0.0.0-20230925135524-a1bc045b3190 - cosmossdk.io/x/tx v0.13.4 + cosmossdk.io/x/tx v0.13.5 cosmossdk.io/x/upgrade v0.0.0-20230613133644-0a778132a60f github.com/cometbft/cometbft v1.0.0-rc1.0.20240908111210-ab0be101882f - github.com/cosmos/cosmos-db v1.0.3-0.20240911104526-ddc3f09bfc22 // indirect github.com/cosmos/cosmos-proto v1.0.0-beta.5 // this version is not used as it is always replaced by the latest Cosmos SDK version github.com/cosmos/cosmos-sdk v0.53.0 @@ -26,15 +25,16 @@ require ( github.com/golang/mock v1.6.0 github.com/spf13/cobra v1.8.1 github.com/stretchr/testify v1.9.0 - google.golang.org/grpc v1.66.2 + google.golang.org/grpc v1.67.1 google.golang.org/protobuf v1.34.2 gotest.tools/v3 v3.5.1 pgregory.net/rapid v1.1.0 ) require ( - cosmossdk.io/core/testing v0.0.0-00010101000000-000000000000 - cosmossdk.io/x/accounts v0.0.0-20240226161501-23359a0b6d91 + cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29 + cosmossdk.io/x/accounts v0.0.0-20240913065641-0064ccbce64e + cosmossdk.io/x/accounts/defaults/base v0.0.0-00010101000000-000000000000 cosmossdk.io/x/accounts/defaults/lockup v0.0.0-20240417181816-5e7aae0db1f5 cosmossdk.io/x/accounts/defaults/multisig v0.0.0-00010101000000-000000000000 cosmossdk.io/x/authz v0.0.0-00010101000000-000000000000 @@ -65,7 +65,7 @@ require ( cloud.google.com/go/storage v1.43.0 // indirect cosmossdk.io/client/v2 v2.0.0-20230630094428-02b760776860 // indirect cosmossdk.io/errors v1.0.1 // indirect - cosmossdk.io/schema v0.2.0 // indirect + cosmossdk.io/schema v0.3.1-0.20240930054013-7c6e0388a3f9 // indirect cosmossdk.io/x/circuit v0.0.0-20230613133644-0a778132a60f // indirect cosmossdk.io/x/epochs v0.0.0-20240522060652-a1ae4c3e0337 // indirect filippo.io/edwards25519 v1.1.0 // indirect @@ -92,6 +92,7 @@ require ( github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect github.com/cometbft/cometbft-db v0.15.0 // indirect github.com/cosmos/btcutil v1.0.5 // indirect + github.com/cosmos/cosmos-db v1.0.3-0.20240911104526-ddc3f09bfc22 // indirect github.com/cosmos/crypto v0.1.2 // indirect github.com/cosmos/go-bip39 v1.0.0 // indirect github.com/cosmos/gogogateway v1.2.0 // indirect @@ -147,7 +148,7 @@ require ( github.com/hashicorp/hcl v1.0.0 // indirect github.com/hashicorp/yamux v0.1.1 // indirect github.com/hdevalence/ed25519consensus v0.2.0 // indirect - github.com/huandu/skiplist v1.2.0 // indirect + github.com/huandu/skiplist v1.2.1 // indirect github.com/iancoleman/strcase v0.3.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect @@ -173,13 +174,13 @@ require ( github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/client_golang v1.20.3 // indirect + github.com/prometheus/client_golang v1.20.4 // indirect github.com/prometheus/client_model v0.6.1 // indirect - github.com/prometheus/common v0.59.1 // indirect + github.com/prometheus/common v0.60.0 // indirect github.com/prometheus/procfs v0.15.1 // indirect github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect github.com/rogpeppe/go-internal v1.12.0 // indirect - github.com/rs/cors v1.11.0 // indirect + github.com/rs/cors v1.11.1 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect github.com/sasha-s/go-deadlock v0.3.5 // indirect @@ -209,7 +210,7 @@ require ( golang.org/x/exp v0.0.0-20240531132922-fd00a4e0eefc // indirect golang.org/x/mod v0.17.0 // indirect golang.org/x/net v0.29.0 // indirect - golang.org/x/oauth2 v0.22.0 // indirect + golang.org/x/oauth2 v0.23.0 // indirect golang.org/x/sync v0.8.0 // indirect golang.org/x/sys v0.25.0 // indirect golang.org/x/term v0.24.0 // indirect @@ -219,7 +220,7 @@ require ( google.golang.org/api v0.192.0 // indirect google.golang.org/genproto v0.0.0-20240814211410-ddb44dafa142 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect sigs.k8s.io/yaml v1.4.0 // indirect @@ -236,9 +237,9 @@ replace ( cosmossdk.io/api => ../api cosmossdk.io/client/v2 => ../client/v2 cosmossdk.io/collections => ../collections - cosmossdk.io/core/testing => ../core/testing cosmossdk.io/store => ../store cosmossdk.io/x/accounts => ../x/accounts + cosmossdk.io/x/accounts/defaults/base => ../x/accounts/defaults/base cosmossdk.io/x/accounts/defaults/lockup => ../x/accounts/defaults/lockup cosmossdk.io/x/accounts/defaults/multisig => ../x/accounts/defaults/multisig cosmossdk.io/x/authz => ../x/authz diff --git a/tests/go.sum b/tests/go.sum index 2427554385a3..b2cfe1aa475e 100644 --- a/tests/go.sum +++ b/tests/go.sum @@ -192,8 +192,10 @@ cloud.google.com/go/webrisk v1.4.0/go.mod h1:Hn8X6Zr+ziE2aNd8SliSDWpEnSS1u4R9+xX cloud.google.com/go/webrisk v1.5.0/go.mod h1:iPG6fr52Tv7sGk0H6qUFzmL3HHZev1htXuWDEEsqMTg= cloud.google.com/go/workflows v1.6.0/go.mod h1:6t9F5h/unJz41YqfBmqSASJSXccBLtD1Vwf+KmJENM0= cloud.google.com/go/workflows v1.7.0/go.mod h1:JhSrZuVZWuiDfKEFxU0/F1PQjmpnpcoISEXH2bcHC3M= -cosmossdk.io/core v1.0.0-alpha.2 h1:epU0Xwces4Rgl5bMhHHkXGaGDcyucNGlC/JDH+Suckg= -cosmossdk.io/core v1.0.0-alpha.2/go.mod h1:abgLjeFLhtuKIYZWSPlVUgQBrKObO7ULV35KYfexE90= +cosmossdk.io/core v1.0.0-alpha.4 h1:9iuroT9ejDYETCsGkzkvs/wAY/5UFl7nCIINFRxyMJY= +cosmossdk.io/core v1.0.0-alpha.4/go.mod h1:3u9cWq1FAVtiiCrDPpo4LhR+9V6k/ycSG4/Y/tREWCY= +cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29 h1:NxxUo0GMJUbIuVg0R70e3cbn9eFTEuMr7ev1AFvypdY= +cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29/go.mod h1:8s2tPeJtSiQuoyPmr2Ag7meikonISO4Fv4MoO8+ORrs= cosmossdk.io/depinject v1.0.0 h1:dQaTu6+O6askNXO06+jyeUAnF2/ssKwrrszP9t5q050= cosmossdk.io/depinject v1.0.0/go.mod h1:zxK/h3HgHoA/eJVtiSsoaRaRA2D5U4cJ5thIG4ssbB8= cosmossdk.io/errors v1.0.1 h1:bzu+Kcr0kS/1DuPBtUFdWjzLqyUuCiyHjyJB6srBV/0= @@ -202,8 +204,8 @@ cosmossdk.io/log v1.4.1 h1:wKdjfDRbDyZRuWa8M+9nuvpVYxrEOwbD/CA8hvhU8QM= cosmossdk.io/log v1.4.1/go.mod h1:k08v0Pyq+gCP6phvdI6RCGhLf/r425UT6Rk/m+o74rU= cosmossdk.io/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE= cosmossdk.io/math v1.3.0/go.mod h1:vnRTxewy+M7BtXBNFybkuhSH4WfedVAAnERHgVFhp3k= -cosmossdk.io/schema v0.2.0 h1:UH5CR1DqUq8yP+5Np8PbvG4YX0zAUsTN2Qk6yThmfMk= -cosmossdk.io/schema v0.2.0/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= +cosmossdk.io/schema v0.3.1-0.20240930054013-7c6e0388a3f9 h1:DmOoS/1PeY6Ih0hAVlJ69kLMUrLV+TCbfICrZtB1vdU= +cosmossdk.io/schema v0.3.1-0.20240930054013-7c6e0388a3f9/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= @@ -585,8 +587,8 @@ github.com/hdevalence/ed25519consensus v0.2.0/go.mod h1:w3BHWjwJbFU29IRHL1Iqkw3s github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/huandu/go-assert v1.1.5 h1:fjemmA7sSfYHJD7CUqs9qTwwfdNAx7/j2/ZlHXzNB3c= github.com/huandu/go-assert v1.1.5/go.mod h1:yOLvuqZwmcHIC5rIzrBhT7D3Q9c3GFnd0JrPVhn/06U= -github.com/huandu/skiplist v1.2.0 h1:gox56QD77HzSC0w+Ws3MH3iie755GBJU1OER3h5VsYw= -github.com/huandu/skiplist v1.2.0/go.mod h1:7v3iFjLcSAzO4fN5B8dvebvo/qsfumiLiDXMrPiHF9w= +github.com/huandu/skiplist v1.2.1 h1:dTi93MgjwErA/8idWTzIw4Y1kZsMWx35fmI2c8Rij7w= +github.com/huandu/skiplist v1.2.1/go.mod h1:7v3iFjLcSAzO4fN5B8dvebvo/qsfumiLiDXMrPiHF9w= github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI= github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= @@ -710,8 +712,8 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= -github.com/prometheus/client_golang v1.20.3 h1:oPksm4K8B+Vt35tUhw6GbSNSgVlVSBH0qELP/7u83l4= -github.com/prometheus/client_golang v1.20.3/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_golang v1.20.4 h1:Tgh3Yr67PaOv/uTqloMsCEdeuFTatm5zIq5+qNN23vI= +github.com/prometheus/client_golang v1.20.4/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -720,8 +722,8 @@ github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= -github.com/prometheus/common v0.59.1 h1:LXb1quJHWm1P6wq/U824uxYi4Sg0oGvNeUm1z5dJoX0= -github.com/prometheus/common v0.59.1/go.mod h1:GpWM7dewqmVYcd7SmRaiWVe9SSqjf0UrwnYnpEZNuT0= +github.com/prometheus/common v0.60.0 h1:+V9PAREWNvJMAuJ1x1BaWl9dewMW4YrHZQbx0sJNllA= +github.com/prometheus/common v0.60.0/go.mod h1:h0LYf1R1deLSKtD4Vdg8gy4RuOvENW2J/h19V5NADQw= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/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= @@ -734,8 +736,8 @@ github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= -github.com/rs/cors v1.11.0 h1:0B9GE/r9Bc2UxRMMtymBkHTenPkHDv0CW4Y98GBY+po= -github.com/rs/cors v1.11.0/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= +github.com/rs/cors v1.11.1 h1:eU3gRzXLRK57F5rKMGMZURNdIG4EoAmX8k94r9wXWHA= +github.com/rs/cors v1.11.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8= github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= @@ -970,8 +972,8 @@ golang.org/x/oauth2 v0.0.0-20220822191816-0ebed06d0094/go.mod h1:h4gKUeWbJ4rQPri golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= golang.org/x/oauth2 v0.1.0/go.mod h1:G9FE4dLTsbXUu90h/Pf85g4w1D+SSAgR+q46nJZ8M4A= -golang.org/x/oauth2 v0.22.0 h1:BzDx2FehcG7jJwgWLELCdmLuxk2i+x9UDpSiss2u0ZA= -golang.org/x/oauth2 v0.22.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/oauth2 v0.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs= +golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= 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= @@ -1325,8 +1327,8 @@ google.golang.org/genproto v0.0.0-20240814211410-ddb44dafa142 h1:oLiyxGgE+rt22du google.golang.org/genproto v0.0.0-20240814211410-ddb44dafa142/go.mod h1:G11eXq53iI5Q+kyNOmCvnzBaxEA2Q/Ik5Tj7nqBE8j4= google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 h1:wKguEg1hsxI2/L3hUYrpo1RVi48K+uTyzKqprwLXsb8= google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142/go.mod h1:d6be+8HhtEtucleCbxpPW9PA9XwISACu8nvpPqF0BVo= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:pPJltXNxVzT4pK9yD8vR9X75DaWYYmLGMsEvBfFQZzQ= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f h1:cUMEy+8oS78BWIH9OWazBkzbr090Od9tWBNtZHkOhf0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -1362,8 +1364,8 @@ google.golang.org/grpc v1.48.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACu google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= google.golang.org/grpc v1.50.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= -google.golang.org/grpc v1.66.2 h1:3QdXkuq3Bkh7w+ywLdLvM56cmGvQHUMZpiCzt6Rqaoo= -google.golang.org/grpc v1.66.2/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y= +google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E= +google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= 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= diff --git a/tests/integration/auth/client/cli/suite_test.go b/tests/integration/auth/client/cli/suite_test.go index b16d469ec445..ea2b929c5b31 100644 --- a/tests/integration/auth/client/cli/suite_test.go +++ b/tests/integration/auth/client/cli/suite_test.go @@ -274,7 +274,6 @@ func (s *CLITestSuite) TestCLIQueryTxCmdByHash() { } for _, tc := range testCases { - tc := tc s.Run(tc.name, func() { cmd := authcli.QueryTxCmd() cmd.SetArgs(tc.args) @@ -340,7 +339,6 @@ func (s *CLITestSuite) TestCLIQueryTxCmdByEvents() { } for _, tc := range testCases { - tc := tc s.Run(tc.name, func() { cmd := authcli.QueryTxCmd() cmd.SetArgs(tc.args) @@ -383,7 +381,6 @@ func (s *CLITestSuite) TestCLIQueryTxsCmdByEvents() { } for _, tc := range testCases { - tc := tc s.Run(tc.name, func() { cmd := authcli.QueryTxsByEventsCmd() @@ -1019,7 +1016,6 @@ func (s *CLITestSuite) TestAuxSigner() { } for _, tc := range testCases { - tc := tc s.Run(tc.name, func() { _, err := govtestutil.MsgSubmitLegacyProposal( s.clientCtx, @@ -1238,7 +1234,6 @@ func (s *CLITestSuite) TestAuxToFeeWithTips() { } for _, tc := range testCases { - tc := tc s.Run(tc.name, func() { res, err := govtestutil.MsgSubmitLegacyProposal( s.clientCtx, diff --git a/tests/integration/auth/keeper/accounts_retro_compatibility_test.go b/tests/integration/auth/keeper/accounts_retro_compatibility_test.go new file mode 100644 index 000000000000..eb27f4ce36b9 --- /dev/null +++ b/tests/integration/auth/keeper/accounts_retro_compatibility_test.go @@ -0,0 +1,157 @@ +package keeper_test + +import ( + "context" + "testing" + + gogotypes "github.com/cosmos/gogoproto/types" + "github.com/stretchr/testify/require" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + + "cosmossdk.io/x/accounts/accountstd" + basev1 "cosmossdk.io/x/accounts/defaults/base/v1" + + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" + authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" +) + +var _ accountstd.Interface = mockRetroCompatAccount{} + +type mockRetroCompatAccount struct { + retroCompat *authtypes.QueryLegacyAccountResponse + address []byte +} + +func (m mockRetroCompatAccount) RegisterInitHandler(builder *accountstd.InitBuilder) { + accountstd.RegisterInitHandler(builder, func(ctx context.Context, req *gogotypes.Empty) (*gogotypes.Empty, error) { + return &gogotypes.Empty{}, nil + }) +} + +func (m mockRetroCompatAccount) RegisterExecuteHandlers(_ *accountstd.ExecuteBuilder) {} + +func (m mockRetroCompatAccount) RegisterQueryHandlers(builder *accountstd.QueryBuilder) { + if m.retroCompat == nil { + return + } + accountstd.RegisterQueryHandler(builder, func(ctx context.Context, req *authtypes.QueryLegacyAccount) (*authtypes.QueryLegacyAccountResponse, error) { + return m.retroCompat, nil + }) +} + +func TestAuthToAccountsGRPCCompat(t *testing.T) { + valid := &mockRetroCompatAccount{ + retroCompat: &authtypes.QueryLegacyAccountResponse{ + Account: &codectypes.Any{}, + Base: &authtypes.BaseAccount{ + Address: "test", + PubKey: nil, + AccountNumber: 10, + Sequence: 20, + }, + }, + } + + noInfo := &mockRetroCompatAccount{ + retroCompat: &authtypes.QueryLegacyAccountResponse{ + Account: &codectypes.Any{}, + }, + } + noImplement := &mockRetroCompatAccount{ + retroCompat: nil, + } + + accs := map[string]accountstd.Interface{ + "valid": valid, + "no_info": noInfo, + "no_implement": noImplement, + } + + f := initFixture(t, accs) + + // init three accounts + for n, a := range accs { + _, addr, err := f.accountsKeeper.Init(f.ctx, n, []byte("me"), &gogotypes.Empty{}, nil) + require.NoError(t, err) + a.(*mockRetroCompatAccount).address = addr + } + + qs := authkeeper.NewQueryServer(f.authKeeper) + + t.Run("account supports info and account query", func(t *testing.T) { + infoResp, err := qs.AccountInfo(f.ctx, &authtypes.QueryAccountInfoRequest{ + Address: f.mustAddr(valid.address), + }) + require.NoError(t, err) + require.Equal(t, infoResp.Info, valid.retroCompat.Base) + + accountResp, err := qs.Account(f.ctx, &authtypes.QueryAccountRequest{ + Address: f.mustAddr(noInfo.address), + }) + require.NoError(t, err) + require.Equal(t, accountResp.Account, valid.retroCompat.Account) + }) + + t.Run("account only supports account query, not info", func(t *testing.T) { + _, err := qs.AccountInfo(f.ctx, &authtypes.QueryAccountInfoRequest{ + Address: f.mustAddr(noInfo.address), + }) + require.Error(t, err) + require.Equal(t, status.Code(err), codes.NotFound) + + resp, err := qs.Account(f.ctx, &authtypes.QueryAccountRequest{ + Address: f.mustAddr(noInfo.address), + }) + require.NoError(t, err) + require.Equal(t, resp.Account, valid.retroCompat.Account) + }) + + t.Run("account does not support any retro compat", func(t *testing.T) { + _, err := qs.AccountInfo(f.ctx, &authtypes.QueryAccountInfoRequest{ + Address: f.mustAddr(noImplement.address), + }) + require.Error(t, err) + require.Equal(t, status.Code(err), codes.NotFound) + + _, err = qs.Account(f.ctx, &authtypes.QueryAccountRequest{ + Address: f.mustAddr(noImplement.address), + }) + + require.Error(t, err) + require.Equal(t, status.Code(err), codes.NotFound) + }) +} + +func TestAccountsBaseAccountRetroCompat(t *testing.T) { + f := initFixture(t, nil) + // init a base acc + anyPk, err := codectypes.NewAnyWithValue(secp256k1.GenPrivKey().PubKey()) + require.NoError(t, err) + + // we init two accounts to have account num not be zero. + _, _, err = f.accountsKeeper.Init(f.ctx, "base", []byte("me"), &basev1.MsgInit{PubKey: anyPk}, nil) + require.NoError(t, err) + + _, addr, err := f.accountsKeeper.Init(f.ctx, "base", []byte("me"), &basev1.MsgInit{PubKey: anyPk}, nil) + require.NoError(t, err) + + // try to query it via auth + qs := authkeeper.NewQueryServer(f.authKeeper) + + r, err := qs.Account(f.ctx, &authtypes.QueryAccountRequest{ + Address: f.mustAddr(addr), + }) + require.NoError(t, err) + require.NotNil(t, r.Account) + + info, err := qs.AccountInfo(f.ctx, &authtypes.QueryAccountInfoRequest{ + Address: f.mustAddr(addr), + }) + require.NoError(t, err) + require.NotNil(t, info.Info) + require.Equal(t, info.Info.PubKey, anyPk) + require.Equal(t, info.Info.AccountNumber, uint64(1)) +} diff --git a/tests/integration/auth/keeper/fixture_test.go b/tests/integration/auth/keeper/fixture_test.go new file mode 100644 index 000000000000..45514c0cdba7 --- /dev/null +++ b/tests/integration/auth/keeper/fixture_test.go @@ -0,0 +1,143 @@ +package keeper_test + +import ( + "testing" + + "gotest.tools/v3/assert" + + "cosmossdk.io/core/appmodule" + "cosmossdk.io/log" + storetypes "cosmossdk.io/store/types" + "cosmossdk.io/x/accounts" + "cosmossdk.io/x/accounts/accountstd" + baseaccount "cosmossdk.io/x/accounts/defaults/base" + accountsv1 "cosmossdk.io/x/accounts/v1" + "cosmossdk.io/x/bank" + bankkeeper "cosmossdk.io/x/bank/keeper" + banktypes "cosmossdk.io/x/bank/types" + minttypes "cosmossdk.io/x/mint/types" + "cosmossdk.io/x/tx/signing" + + "github.com/cosmos/cosmos-sdk/baseapp" + "github.com/cosmos/cosmos-sdk/codec" + addresscodec "github.com/cosmos/cosmos-sdk/codec/address" + codectestutil "github.com/cosmos/cosmos-sdk/codec/testutil" + "github.com/cosmos/cosmos-sdk/runtime" + "github.com/cosmos/cosmos-sdk/testutil/integration" + sdk "github.com/cosmos/cosmos-sdk/types" + moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil" + "github.com/cosmos/cosmos-sdk/x/auth" + authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper" + authsims "github.com/cosmos/cosmos-sdk/x/auth/simulation" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" +) + +type fixture struct { + app *integration.App + + cdc codec.Codec + ctx sdk.Context + + authKeeper authkeeper.AccountKeeper + accountsKeeper accounts.Keeper + bankKeeper bankkeeper.Keeper +} + +func (f fixture) mustAddr(address []byte) string { + s, _ := f.authKeeper.AddressCodec().BytesToString(address) + return s +} + +func initFixture(t *testing.T, extraAccs map[string]accountstd.Interface) *fixture { + t.Helper() + keys := storetypes.NewKVStoreKeys( + authtypes.StoreKey, banktypes.StoreKey, accounts.StoreKey, + ) + encodingCfg := moduletestutil.MakeTestEncodingConfig(codectestutil.CodecOptions{}, auth.AppModule{}, bank.AppModule{}, accounts.AppModule{}) + cdc := encodingCfg.Codec + + logger := log.NewTestLogger(t) + cms := integration.CreateMultiStore(keys, logger) + + newCtx := sdk.NewContext(cms, true, logger) + + router := baseapp.NewMsgServiceRouter() + queryRouter := baseapp.NewGRPCQueryRouter() + + handler := directHandler{} + account := baseaccount.NewAccount("base", signing.NewHandlerMap(handler), baseaccount.WithSecp256K1PubKey()) + + var accs []accountstd.AccountCreatorFunc + for name, acc := range extraAccs { + f := accountstd.AddAccount(name, func(_ accountstd.Dependencies) (accountstd.Interface, error) { + return acc, nil + }) + accs = append(accs, f) + } + accountsKeeper, err := accounts.NewKeeper( + cdc, + runtime.NewEnvironment(runtime.NewKVStoreService(keys[accounts.StoreKey]), log.NewNopLogger(), runtime.EnvWithQueryRouterService(queryRouter), runtime.EnvWithMsgRouterService(router)), + addresscodec.NewBech32Codec("cosmos"), + cdc.InterfaceRegistry(), + append(accs, account)..., + ) + assert.NilError(t, err) + accountsv1.RegisterQueryServer(queryRouter, accounts.NewQueryServer(accountsKeeper)) + + authority := authtypes.NewModuleAddress("gov") + + authKeeper := authkeeper.NewAccountKeeper( + runtime.NewEnvironment(runtime.NewKVStoreService(keys[authtypes.StoreKey]), log.NewNopLogger()), + cdc, + authtypes.ProtoBaseAccount, + accountsKeeper, + map[string][]string{minttypes.ModuleName: {authtypes.Minter}}, + addresscodec.NewBech32Codec(sdk.Bech32MainPrefix), + sdk.Bech32MainPrefix, + authority.String(), + ) + + blockedAddresses := map[string]bool{ + authKeeper.GetAuthority(): false, + } + bankKeeper := bankkeeper.NewBaseKeeper( + runtime.NewEnvironment(runtime.NewKVStoreService(keys[banktypes.StoreKey]), log.NewNopLogger()), + cdc, + authKeeper, + blockedAddresses, + authority.String(), + ) + + params := banktypes.DefaultParams() + assert.NilError(t, bankKeeper.SetParams(newCtx, params)) + + accountsModule := accounts.NewAppModule(cdc, accountsKeeper) + authModule := auth.NewAppModule(cdc, authKeeper, accountsKeeper, authsims.RandomGenesisAccounts, nil) + bankModule := bank.NewAppModule(cdc, bankKeeper, authKeeper) + + integrationApp := integration.NewIntegrationApp(newCtx, logger, keys, cdc, + encodingCfg.InterfaceRegistry.SigningContext().AddressCodec(), + encodingCfg.InterfaceRegistry.SigningContext().ValidatorAddressCodec(), + map[string]appmodule.AppModule{ + accounts.ModuleName: accountsModule, + authtypes.ModuleName: authModule, + banktypes.ModuleName: bankModule, + }, router, queryRouter) + + authtypes.RegisterInterfaces(cdc.InterfaceRegistry()) + banktypes.RegisterInterfaces(cdc.InterfaceRegistry()) + + authtypes.RegisterMsgServer(integrationApp.MsgServiceRouter(), authkeeper.NewMsgServerImpl(authKeeper)) + authtypes.RegisterQueryServer(integrationApp.QueryHelper(), authkeeper.NewQueryServer(authKeeper)) + + banktypes.RegisterMsgServer(router, bankkeeper.NewMsgServerImpl(bankKeeper)) + + return &fixture{ + app: integrationApp, + cdc: cdc, + ctx: newCtx, + accountsKeeper: accountsKeeper, + authKeeper: authKeeper, + bankKeeper: bankKeeper, + } +} diff --git a/tests/integration/auth/keeper/migrate_x_accounts_test.go b/tests/integration/auth/keeper/migrate_x_accounts_test.go new file mode 100644 index 000000000000..452a7e1d9666 --- /dev/null +++ b/tests/integration/auth/keeper/migrate_x_accounts_test.go @@ -0,0 +1,100 @@ +package keeper_test + +import ( + "testing" + + "github.com/stretchr/testify/require" + + basev1 "cosmossdk.io/x/accounts/defaults/base/v1" + + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" +) + +func TestMigrateToAccounts(t *testing.T) { + f := initFixture(t, nil) + + // create a module account + modAcc := &authtypes.ModuleAccount{ + BaseAccount: &authtypes.BaseAccount{ + Address: f.mustAddr([]byte("cookies")), + PubKey: nil, + AccountNumber: 0, + Sequence: 0, + }, + Name: "cookies", + Permissions: nil, + } + updatedMod := f.authKeeper.NewAccount(f.ctx, modAcc) + f.authKeeper.SetAccount(f.ctx, updatedMod) + + // create account + msgSrv := authkeeper.NewMsgServerImpl(f.authKeeper) + privKey := secp256k1.GenPrivKey() + addr := sdk.AccAddress(privKey.PubKey().Address()) + + acc := f.authKeeper.NewAccountWithAddress(f.ctx, addr) + require.NoError(t, acc.SetPubKey(privKey.PubKey())) + f.authKeeper.SetAccount(f.ctx, acc) + + t.Run("account does not exist", func(t *testing.T) { + resp, err := msgSrv.MigrateAccount(f.ctx, &authtypes.MsgMigrateAccount{ + Signer: f.mustAddr([]byte("notexist")), + AccountType: "base", + AccountInitMsg: nil, + }) + require.Nil(t, resp) + require.ErrorIs(t, err, sdkerrors.ErrUnknownAddress) + }) + + t.Run("invalid account type", func(t *testing.T) { + resp, err := msgSrv.MigrateAccount(f.ctx, &authtypes.MsgMigrateAccount{ + Signer: f.mustAddr(updatedMod.GetAddress()), + AccountType: "base", + AccountInitMsg: nil, + }) + require.Nil(t, resp) + require.ErrorContains(t, err, "only BaseAccount can be migrated") + }) + + t.Run("success", func(t *testing.T) { + pk, err := codectypes.NewAnyWithValue(privKey.PubKey()) + require.NoError(t, err) + + migrateMsg := &basev1.MsgInit{ + PubKey: pk, + InitSequence: 100, + } + + initMsgAny, err := codectypes.NewAnyWithValue(migrateMsg) + require.NoError(t, err) + + resp, err := msgSrv.MigrateAccount(f.ctx, &authtypes.MsgMigrateAccount{ + Signer: f.mustAddr(addr), + AccountType: "base", + AccountInitMsg: initMsgAny, + }) + require.NoError(t, err) + + // check response semantics. + require.Equal(t, resp.InitResponse.TypeUrl, "/cosmos.accounts.defaults.base.v1.MsgInitResponse") + require.NotNil(t, resp.InitResponse.Value) + + // check the account was removed from x/auth and added to x/accounts + require.Nil(t, f.authKeeper.GetAccount(f.ctx, addr)) + require.True(t, f.accountsKeeper.IsAccountsModuleAccount(f.ctx, addr)) + + // check the init information is correctly propagated. + seq, err := f.accountsKeeper.Query(f.ctx, addr, &basev1.QuerySequence{}) + require.NoError(t, err) + require.Equal(t, migrateMsg.InitSequence, seq.(*basev1.QuerySequenceResponse).Sequence) + + pkResp, err := f.accountsKeeper.Query(f.ctx, addr, &basev1.QueryPubKey{}) + require.NoError(t, err) + require.Equal(t, migrateMsg.PubKey, pkResp.(*basev1.QueryPubKeyResponse).PubKey) + }) +} diff --git a/tests/integration/auth/keeper/msg_server_test.go b/tests/integration/auth/keeper/msg_server_test.go index d9985add6a61..076f33620508 100644 --- a/tests/integration/auth/keeper/msg_server_test.go +++ b/tests/integration/auth/keeper/msg_server_test.go @@ -9,46 +9,18 @@ import ( "gotest.tools/v3/assert" signingv1beta1 "cosmossdk.io/api/cosmos/tx/signing/v1beta1" - "cosmossdk.io/core/appmodule" - "cosmossdk.io/log" sdkmath "cosmossdk.io/math" - storetypes "cosmossdk.io/store/types" - "cosmossdk.io/x/accounts" - baseaccount "cosmossdk.io/x/accounts/defaults/base" - "cosmossdk.io/x/bank" - bankkeeper "cosmossdk.io/x/bank/keeper" "cosmossdk.io/x/bank/testutil" banktypes "cosmossdk.io/x/bank/types" - minttypes "cosmossdk.io/x/mint/types" "cosmossdk.io/x/tx/signing" - "github.com/cosmos/cosmos-sdk/baseapp" - "github.com/cosmos/cosmos-sdk/codec" - addresscodec "github.com/cosmos/cosmos-sdk/codec/address" - codectestutil "github.com/cosmos/cosmos-sdk/codec/testutil" codectypes "github.com/cosmos/cosmos-sdk/codec/types" - "github.com/cosmos/cosmos-sdk/runtime" "github.com/cosmos/cosmos-sdk/testutil/integration" simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" sdk "github.com/cosmos/cosmos-sdk/types" - moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil" - "github.com/cosmos/cosmos-sdk/x/auth" - authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper" - authsims "github.com/cosmos/cosmos-sdk/x/auth/simulation" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" ) -type fixture struct { - app *integration.App - - cdc codec.Codec - ctx sdk.Context - - authKeeper authkeeper.AccountKeeper - accountsKeeper accounts.Keeper - bankKeeper bankkeeper.Keeper -} - var _ signing.SignModeHandler = directHandler{} type directHandler struct{} @@ -61,94 +33,9 @@ func (s directHandler) GetSignBytes(_ context.Context, _ signing.SignerData, _ s panic("not implemented") } -func initFixture(t *testing.T) *fixture { - t.Helper() - keys := storetypes.NewKVStoreKeys( - authtypes.StoreKey, banktypes.StoreKey, accounts.StoreKey, - ) - encodingCfg := moduletestutil.MakeTestEncodingConfig(codectestutil.CodecOptions{}, auth.AppModule{}, bank.AppModule{}, accounts.AppModule{}) - cdc := encodingCfg.Codec - - logger := log.NewTestLogger(t) - cms := integration.CreateMultiStore(keys, logger) - - newCtx := sdk.NewContext(cms, true, logger) - - router := baseapp.NewMsgServiceRouter() - queryRouter := baseapp.NewGRPCQueryRouter() - - handler := directHandler{} - account := baseaccount.NewAccount("base", signing.NewHandlerMap(handler), baseaccount.WithSecp256K1PubKey()) - accountsKeeper, err := accounts.NewKeeper( - cdc, - runtime.NewEnvironment(runtime.NewKVStoreService(keys[accounts.StoreKey]), log.NewNopLogger(), runtime.EnvWithQueryRouterService(queryRouter), runtime.EnvWithMsgRouterService(router)), - addresscodec.NewBech32Codec("cosmos"), - cdc.InterfaceRegistry(), - account, - ) - assert.NilError(t, err) - - authority := authtypes.NewModuleAddress("gov") - - authKeeper := authkeeper.NewAccountKeeper( - runtime.NewEnvironment(runtime.NewKVStoreService(keys[authtypes.StoreKey]), log.NewNopLogger()), - cdc, - authtypes.ProtoBaseAccount, - accountsKeeper, - map[string][]string{minttypes.ModuleName: {authtypes.Minter}}, - addresscodec.NewBech32Codec(sdk.Bech32MainPrefix), - sdk.Bech32MainPrefix, - authority.String(), - ) - - blockedAddresses := map[string]bool{ - authKeeper.GetAuthority(): false, - } - bankKeeper := bankkeeper.NewBaseKeeper( - runtime.NewEnvironment(runtime.NewKVStoreService(keys[banktypes.StoreKey]), log.NewNopLogger()), - cdc, - authKeeper, - blockedAddresses, - authority.String(), - ) - - params := banktypes.DefaultParams() - assert.NilError(t, bankKeeper.SetParams(newCtx, params)) - - accountsModule := accounts.NewAppModule(cdc, accountsKeeper) - authModule := auth.NewAppModule(cdc, authKeeper, accountsKeeper, authsims.RandomGenesisAccounts, nil) - bankModule := bank.NewAppModule(cdc, bankKeeper, authKeeper) - - integrationApp := integration.NewIntegrationApp(newCtx, logger, keys, cdc, - encodingCfg.InterfaceRegistry.SigningContext().AddressCodec(), - encodingCfg.InterfaceRegistry.SigningContext().ValidatorAddressCodec(), - map[string]appmodule.AppModule{ - accounts.ModuleName: accountsModule, - authtypes.ModuleName: authModule, - banktypes.ModuleName: bankModule, - }, router, queryRouter) - - authtypes.RegisterInterfaces(cdc.InterfaceRegistry()) - banktypes.RegisterInterfaces(cdc.InterfaceRegistry()) - - authtypes.RegisterMsgServer(integrationApp.MsgServiceRouter(), authkeeper.NewMsgServerImpl(authKeeper)) - authtypes.RegisterQueryServer(integrationApp.QueryHelper(), authkeeper.NewQueryServer(authKeeper)) - - banktypes.RegisterMsgServer(router, bankkeeper.NewMsgServerImpl(bankKeeper)) - - return &fixture{ - app: integrationApp, - cdc: cdc, - ctx: newCtx, - accountsKeeper: accountsKeeper, - authKeeper: authKeeper, - bankKeeper: bankKeeper, - } -} - func TestAsyncExec(t *testing.T) { t.Parallel() - f := initFixture(t) + f := initFixture(t, nil) addrs := simtestutil.CreateIncrementalAccounts(2) coins := sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(10))) @@ -250,7 +137,6 @@ func TestAsyncExec(t *testing.T) { } for _, tc := range testCases { - tc := tc t.Run(tc.name, func(t *testing.T) { res, err := f.app.RunMsg( tc.req, diff --git a/tests/integration/bank/app_test.go b/tests/integration/bank/app_test.go index 6db4b4a0ff70..bc6cbf6d8a5c 100644 --- a/tests/integration/bank/app_test.go +++ b/tests/integration/bank/app_test.go @@ -97,6 +97,7 @@ func createTestSuite(t *testing.T, genesisAccounts []authtypes.GenesisAccount) s configurator.AuthModule(), configurator.StakingModule(), configurator.TxModule(), + configurator.ValidateModule(), configurator.ConsensusModule(), configurator.BankModule(), configurator.GovModule(), diff --git a/tests/integration/bank/keeper/deterministic_test.go b/tests/integration/bank/keeper/deterministic_test.go index 575fdaead315..7233a4d0ee86 100644 --- a/tests/integration/bank/keeper/deterministic_test.go +++ b/tests/integration/bank/keeper/deterministic_test.go @@ -200,7 +200,9 @@ func TestGRPCQueryAllBalances(t *testing.T) { for i := 0; i < numCoins; i++ { coin := getCoin(rt) - + if exists, _ := coins.Find(coin.Denom); exists { + t.Skip("duplicate denom") + } // NewCoins sorts the denoms coins = sdk.NewCoins(append(coins, coin)...) } diff --git a/tests/integration/distribution/appconfig.go b/tests/integration/distribution/appconfig.go index 62cf1fc57b4b..1342dabef75f 100644 --- a/tests/integration/distribution/appconfig.go +++ b/tests/integration/distribution/appconfig.go @@ -21,6 +21,7 @@ var AppConfig = configurator.NewAppConfig( configurator.BankModule(), configurator.StakingModule(), configurator.TxModule(), + configurator.ValidateModule(), configurator.ConsensusModule(), configurator.GenutilModule(), configurator.DistributionModule(), diff --git a/tests/integration/distribution/cli_tx_test.go b/tests/integration/distribution/cli_tx_test.go index 06f3012128db..0eb26d978c2f 100644 --- a/tests/integration/distribution/cli_tx_test.go +++ b/tests/integration/distribution/cli_tx_test.go @@ -111,8 +111,6 @@ func (s *CLITestSuite) TestTxWithdrawAllRewardsCmd() { } for _, tc := range testCases { - tc := tc - s.Run(tc.name, func() { cmd := cli.NewWithdrawAllRewardsCmd() diff --git a/tests/integration/distribution/keeper/msg_server_test.go b/tests/integration/distribution/keeper/msg_server_test.go index a7be5653566a..7ab94c01a3e1 100644 --- a/tests/integration/distribution/keeper/msg_server_test.go +++ b/tests/integration/distribution/keeper/msg_server_test.go @@ -146,8 +146,8 @@ func initFixture(t *testing.T) *fixture { authModule := auth.NewAppModule(cdc, accountKeeper, acctsModKeeper, authsims.RandomGenesisAccounts, nil) bankModule := bank.NewAppModule(cdc, bankKeeper, accountKeeper) - stakingModule := staking.NewAppModule(cdc, stakingKeeper, accountKeeper, bankKeeper) - distrModule := distribution.NewAppModule(cdc, distrKeeper, accountKeeper, bankKeeper, stakingKeeper) + stakingModule := staking.NewAppModule(cdc, stakingKeeper) + distrModule := distribution.NewAppModule(cdc, distrKeeper, stakingKeeper) poolModule := protocolpool.NewAppModule(cdc, poolKeeper, accountKeeper, bankKeeper) consensusModule := consensus.NewAppModule(cdc, consensusParamsKeeper) @@ -331,7 +331,6 @@ func TestMsgWithdrawDelegatorReward(t *testing.T) { height := f.app.LastBlockHeight() for _, tc := range testCases { - tc := tc t.Run(tc.name, func(t *testing.T) { res, err := f.app.RunMsg( tc.msg, @@ -469,7 +468,6 @@ func TestMsgSetWithdrawAddress(t *testing.T) { }, } for _, tc := range testCases { - tc := tc t.Run(tc.name, func(t *testing.T) { tc.preRun() res, err := f.app.RunMsg( @@ -566,7 +564,6 @@ func TestMsgWithdrawValidatorCommission(t *testing.T) { } for _, tc := range testCases { - tc := tc t.Run(tc.name, func(t *testing.T) { res, err := f.app.RunMsg( tc.msg, @@ -600,7 +597,6 @@ func TestMsgWithdrawValidatorCommission(t *testing.T) { }, remainder.Commission) } }) - } } @@ -666,7 +662,6 @@ func TestMsgFundCommunityPool(t *testing.T) { }, } for _, tc := range testCases { - tc := tc t.Run(tc.name, func(t *testing.T) { res, err := f.app.RunMsg( tc.msg, @@ -808,7 +803,6 @@ func TestMsgUpdateParams(t *testing.T) { } for _, tc := range testCases { - tc := tc t.Run(tc.name, func(t *testing.T) { res, err := f.app.RunMsg( tc.msg, @@ -891,7 +885,6 @@ func TestMsgCommunityPoolSpend(t *testing.T) { }, } for _, tc := range testCases { - tc := tc t.Run(tc.name, func(t *testing.T) { res, err := f.app.RunMsg( tc.msg, @@ -992,7 +985,6 @@ func TestMsgDepositValidatorRewardsPool(t *testing.T) { } for _, tc := range testCases { - tc := tc t.Run(tc.name, func(t *testing.T) { res, err := f.app.RunMsg( tc.msg, diff --git a/tests/integration/evidence/app_config.go b/tests/integration/evidence/app_config.go index 02640cf9a0b1..f328a31b056a 100644 --- a/tests/integration/evidence/app_config.go +++ b/tests/integration/evidence/app_config.go @@ -21,6 +21,7 @@ var AppConfig = configurator.NewAppConfig( configurator.StakingModule(), configurator.SlashingModule(), configurator.TxModule(), + configurator.ValidateModule(), configurator.ConsensusModule(), configurator.EvidenceModule(), configurator.GenutilModule(), diff --git a/tests/integration/evidence/keeper/infraction_test.go b/tests/integration/evidence/keeper/infraction_test.go index b666bd3fcb5b..6be779630903 100644 --- a/tests/integration/evidence/keeper/infraction_test.go +++ b/tests/integration/evidence/keeper/infraction_test.go @@ -154,14 +154,14 @@ func initFixture(tb testing.TB) *fixture { stakingKeeper.SetHooks(stakingtypes.NewMultiStakingHooks(slashingKeeper.Hooks())) - evidenceKeeper := keeper.NewKeeper(cdc, runtime.NewEnvironment(runtime.NewKVStoreService(keys[evidencetypes.StoreKey]), log.NewNopLogger(), runtime.EnvWithQueryRouterService(grpcQueryRouter), runtime.EnvWithMsgRouterService(msgRouter)), stakingKeeper, slashingKeeper, consensusParamsKeeper, addresscodec.NewBech32Codec(sdk.Bech32PrefixAccAddr)) + evidenceKeeper := keeper.NewKeeper(cdc, runtime.NewEnvironment(runtime.NewKVStoreService(keys[evidencetypes.StoreKey]), log.NewNopLogger(), runtime.EnvWithQueryRouterService(grpcQueryRouter), runtime.EnvWithMsgRouterService(msgRouter)), stakingKeeper, slashingKeeper, consensusParamsKeeper, addresscodec.NewBech32Codec(sdk.Bech32PrefixAccAddr), stakingKeeper.ConsensusAddressCodec()) router := evidencetypes.NewRouter() router = router.AddRoute(evidencetypes.RouteEquivocation, testEquivocationHandler(evidenceKeeper)) evidenceKeeper.SetRouter(router) authModule := auth.NewAppModule(cdc, accountKeeper, acctsModKeeper, authsims.RandomGenesisAccounts, nil) bankModule := bank.NewAppModule(cdc, bankKeeper, accountKeeper) - stakingModule := staking.NewAppModule(cdc, stakingKeeper, accountKeeper, bankKeeper) + stakingModule := staking.NewAppModule(cdc, stakingKeeper) slashingModule := slashing.NewAppModule(cdc, slashingKeeper, accountKeeper, bankKeeper, stakingKeeper, cdc.InterfaceRegistry(), cometInfoService) evidenceModule := evidence.NewAppModule(cdc, *evidenceKeeper, cometInfoService) consensusModule := consensus.NewAppModule(cdc, consensusParamsKeeper) diff --git a/tests/integration/example/example_test.go b/tests/integration/example/example_test.go index ced052da114f..7ff625634ac9 100644 --- a/tests/integration/example/example_test.go +++ b/tests/integration/example/example_test.go @@ -74,8 +74,8 @@ func Example() { // here bankkeeper and staking keeper is nil because we are not testing them // subspace is nil because we don't test params (which is legacy anyway) - mintKeeper := mintkeeper.NewKeeper(encodingCfg.Codec, runtime.NewEnvironment(runtime.NewKVStoreService(keys[minttypes.StoreKey]), logger), nil, accountKeeper, nil, authtypes.FeeCollectorName, authority) - mintModule := mint.NewAppModule(encodingCfg.Codec, mintKeeper, accountKeeper, nil) + mintKeeper := mintkeeper.NewKeeper(encodingCfg.Codec, runtime.NewEnvironment(runtime.NewKVStoreService(keys[minttypes.StoreKey]), logger), accountKeeper, nil, authtypes.FeeCollectorName, authority) + mintModule := mint.NewAppModule(encodingCfg.Codec, mintKeeper, accountKeeper) // create the application and register all the modules from the previous step integrationApp := integration.NewIntegrationApp( diff --git a/tests/integration/genutil/genaccount_test.go b/tests/integration/genutil/genaccount_test.go index 739adda97d2b..1b1bd420e99e 100644 --- a/tests/integration/genutil/genaccount_test.go +++ b/tests/integration/genutil/genaccount_test.go @@ -72,7 +72,6 @@ func TestAddGenesisAccountCmd(t *testing.T) { } for _, tc := range tests { - tc := tc t.Run(tc.name, func(t *testing.T) { home := t.TempDir() logger := log.NewNopLogger() @@ -217,7 +216,6 @@ func TestBulkAddGenesisAccountCmd(t *testing.T) { } for _, tc := range tests { - tc := tc t.Run(tc.name, func(t *testing.T) { home := t.TempDir() logger := log.NewNopLogger() diff --git a/tests/integration/genutil/init_test.go b/tests/integration/genutil/init_test.go index 9116db0ce8fe..b49dbc6a7458 100644 --- a/tests/integration/genutil/init_test.go +++ b/tests/integration/genutil/init_test.go @@ -37,7 +37,7 @@ import ( ) var testMbm = module.NewManager( - staking.NewAppModule(makeCodec(), nil, nil, nil), + staking.NewAppModule(makeCodec(), nil), genutil.NewAppModule(makeCodec(), nil, nil, nil, nil, nil), ) @@ -61,7 +61,6 @@ func TestInitCmd(t *testing.T) { } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { home := t.TempDir() logger := log.NewNopLogger() diff --git a/tests/integration/gov/common_test.go b/tests/integration/gov/common_test.go index ced80fc6ad84..f84bbc81a857 100644 --- a/tests/integration/gov/common_test.go +++ b/tests/integration/gov/common_test.go @@ -34,7 +34,7 @@ import ( var ( valTokens = sdk.TokensFromConsensusPower(42, sdk.DefaultPowerReduction) TestProposal = v1beta1.NewTextProposal("Test", "description") - TestDescription = stakingtypes.NewDescription("T", "E", "S", "T", "Z") + TestDescription = stakingtypes.NewDescription("T", "E", "S", "T", "Z", stakingtypes.Metadata{}) TestCommissionRates = stakingtypes.NewCommissionRates(math.LegacyZeroDec(), math.LegacyZeroDec(), math.LegacyZeroDec()) ) diff --git a/tests/integration/gov/keeper/keeper_test.go b/tests/integration/gov/keeper/keeper_test.go index da20fc9b2b98..f1f94f575d58 100644 --- a/tests/integration/gov/keeper/keeper_test.go +++ b/tests/integration/gov/keeper/keeper_test.go @@ -149,7 +149,7 @@ func initFixture(tb testing.TB) *fixture { authModule := auth.NewAppModule(cdc, accountKeeper, acctsModKeeper, authsims.RandomGenesisAccounts, nil) bankModule := bank.NewAppModule(cdc, bankKeeper, accountKeeper) - stakingModule := staking.NewAppModule(cdc, stakingKeeper, accountKeeper, bankKeeper) + stakingModule := staking.NewAppModule(cdc, stakingKeeper) govModule := gov.NewAppModule(cdc, govKeeper, accountKeeper, bankKeeper, poolKeeper) consensusModule := consensus.NewAppModule(cdc, consensusParamsKeeper) diff --git a/tests/integration/mint/app_config.go b/tests/integration/mint/app_config.go index 438b652f4ca5..b074d723d9cb 100644 --- a/tests/integration/mint/app_config.go +++ b/tests/integration/mint/app_config.go @@ -19,6 +19,7 @@ var AppConfig = configurator.NewAppConfig( configurator.BankModule(), configurator.StakingModule(), configurator.TxModule(), + configurator.ValidateModule(), configurator.ConsensusModule(), configurator.GenutilModule(), configurator.MintModule(), diff --git a/tests/integration/protocolpool/app_config.go b/tests/integration/protocolpool/app_config.go index 686a6b93dcd6..34f39a3111ac 100644 --- a/tests/integration/protocolpool/app_config.go +++ b/tests/integration/protocolpool/app_config.go @@ -21,6 +21,7 @@ var AppConfig = configurator.NewAppConfig( configurator.BankModule(), configurator.StakingModule(), configurator.TxModule(), + configurator.ValidateModule(), configurator.ConsensusModule(), configurator.GenutilModule(), configurator.MintModule(), diff --git a/tests/integration/rapidgen/rapidgen.go b/tests/integration/rapidgen/rapidgen.go index e33e794b00f2..0060ca1976ce 100644 --- a/tests/integration/rapidgen/rapidgen.go +++ b/tests/integration/rapidgen/rapidgen.go @@ -222,7 +222,6 @@ var ( NonsignableTypes = []GeneratedType{ GenType(&authtypes.Params{}, &authapi.Params{}, GenOpts), GenType(&authtypes.BaseAccount{}, &authapi.BaseAccount{}, GenOpts.WithAnyTypes(&ed25519.PubKey{})), - GenType(&authtypes.ModuleAccount{}, &authapi.ModuleAccount{}, GenOpts.WithAnyTypes(&ed25519.PubKey{})), GenType(&authtypes.ModuleCredential{}, &authapi.ModuleCredential{}, GenOpts), GenType(&authztypes.GenericAuthorization{}, &authzapi.GenericAuthorization{}, GenOpts), @@ -260,7 +259,9 @@ var ( GenType(&slashingtypes.Params{}, &slashingapi.Params{}, GenOpts.WithDisallowNil()), - GenType(&stakingtypes.StakeAuthorization{}, &stakingapi.StakeAuthorization{}, GenOpts), + // JSON ordering of one of fields to be fixed in https://github.com/cosmos/cosmos-sdk/pull/21782 + // TODO uncomment once merged + // GenType(&stakingtypes.StakeAuthorization{}, &stakingapi.StakeAuthorization{}, GenOpts), GenType(&upgradetypes.CancelSoftwareUpgradeProposal{}, &upgradeapi.CancelSoftwareUpgradeProposal{}, GenOpts), //nolint:staticcheck // testing legacy code path GenType(&upgradetypes.SoftwareUpgradeProposal{}, &upgradeapi.SoftwareUpgradeProposal{}, GenOpts.WithDisallowNil()), //nolint:staticcheck // testing legacy code path diff --git a/tests/integration/runtime/query_test.go b/tests/integration/runtime/query_test.go index 22b261206c36..f1c2b82ab433 100644 --- a/tests/integration/runtime/query_test.go +++ b/tests/integration/runtime/query_test.go @@ -46,6 +46,7 @@ func initFixture(t assert.TestingT) *fixture { configurator.AccountsModule(), configurator.AuthModule(), configurator.TxModule(), + configurator.ValidateModule(), configurator.ConsensusModule(), configurator.BankModule(), configurator.StakingModule(), diff --git a/tests/integration/server/grpc/out_of_gas_test.go b/tests/integration/server/grpc/out_of_gas_test.go index 3e26d54c4f1b..eabd41fc754d 100644 --- a/tests/integration/server/grpc/out_of_gas_test.go +++ b/tests/integration/server/grpc/out_of_gas_test.go @@ -45,6 +45,7 @@ func (s *IntegrationTestOutOfGasSuite) SetupSuite() { configurator.StakingModule(), configurator.ConsensusModule(), configurator.TxModule(), + configurator.ValidateModule(), ), baseapp.SetQueryGasLimit(10)) s.NoError(err) s.cfg.NumValidators = 1 diff --git a/tests/integration/server/grpc/server_test.go b/tests/integration/server/grpc/server_test.go index c0cc8748a6bd..e8d6d180b435 100644 --- a/tests/integration/server/grpc/server_test.go +++ b/tests/integration/server/grpc/server_test.go @@ -56,6 +56,7 @@ func (s *IntegrationTestSuite) SetupSuite() { configurator.StakingModule(), configurator.ConsensusModule(), configurator.TxModule(), + configurator.ValidateModule(), )) s.NoError(err) s.cfg.NumValidators = 1 diff --git a/tests/integration/slashing/app_config.go b/tests/integration/slashing/app_config.go index f649e196fb75..415bea47145d 100644 --- a/tests/integration/slashing/app_config.go +++ b/tests/integration/slashing/app_config.go @@ -23,6 +23,7 @@ var AppConfig = configurator.NewAppConfig( configurator.StakingModule(), configurator.SlashingModule(), configurator.TxModule(), + configurator.ValidateModule(), configurator.ConsensusModule(), configurator.GenutilModule(), configurator.MintModule(), diff --git a/tests/integration/slashing/keeper/keeper_test.go b/tests/integration/slashing/keeper/keeper_test.go index a50dcac4fa05..e961dc68233d 100644 --- a/tests/integration/slashing/keeper/keeper_test.go +++ b/tests/integration/slashing/keeper/keeper_test.go @@ -126,7 +126,7 @@ func initFixture(tb testing.TB) *fixture { slashingKeeper := slashingkeeper.NewKeeper(runtime.NewEnvironment(runtime.NewKVStoreService(keys[slashingtypes.StoreKey]), log.NewNopLogger(), runtime.EnvWithQueryRouterService(queryRouter), runtime.EnvWithMsgRouterService(msgRouter)), cdc, &codec.LegacyAmino{}, stakingKeeper, authority.String()) bankModule := bank.NewAppModule(cdc, bankKeeper, accountKeeper) - stakingModule := staking.NewAppModule(cdc, stakingKeeper, accountKeeper, bankKeeper) + stakingModule := staking.NewAppModule(cdc, stakingKeeper) slashingModule := slashing.NewAppModule(cdc, slashingKeeper, accountKeeper, bankKeeper, stakingKeeper, cdc.InterfaceRegistry(), cometInfoService) consensusModule := consensus.NewAppModule(cdc, consensusParamsKeeper) diff --git a/tests/integration/slashing/slashing_test.go b/tests/integration/slashing/slashing_test.go index 035d013b369e..6c60ce295b5d 100644 --- a/tests/integration/slashing/slashing_test.go +++ b/tests/integration/slashing/slashing_test.go @@ -67,6 +67,7 @@ func TestSlashingMsgs(t *testing.T) { configurator.StakingModule(), configurator.SlashingModule(), configurator.TxModule(), + configurator.ValidateModule(), configurator.ConsensusModule(), configurator.BankModule(), ), @@ -82,7 +83,7 @@ func TestSlashingMsgs(t *testing.T) { require.NoError(t, err) - description := stakingtypes.NewDescription("foo_moniker", "", "", "", "") + description := stakingtypes.NewDescription("foo_moniker", "", "", "", "", stakingtypes.Metadata{}) commission := stakingtypes.NewCommissionRates(math.LegacyZeroDec(), math.LegacyZeroDec(), math.LegacyZeroDec()) addrStrVal, err := valaddrCodec.BytesToString(addr1) diff --git a/tests/integration/staking/app_config.go b/tests/integration/staking/app_config.go index 9bfb400e6c09..4c08ff1faef6 100644 --- a/tests/integration/staking/app_config.go +++ b/tests/integration/staking/app_config.go @@ -22,6 +22,7 @@ var AppConfig = configurator.NewAppConfig( configurator.BankModule(), configurator.StakingModule(), configurator.TxModule(), + configurator.ValidateModule(), configurator.ConsensusModule(), configurator.GenutilModule(), configurator.MintModule(), diff --git a/tests/integration/staking/keeper/common_test.go b/tests/integration/staking/keeper/common_test.go index 26d0e217afaa..e3963efb7bb7 100644 --- a/tests/integration/staking/keeper/common_test.go +++ b/tests/integration/staking/keeper/common_test.go @@ -170,7 +170,7 @@ func initFixture(tb testing.TB) *fixture { authModule := auth.NewAppModule(cdc, accountKeeper, acctsModKeeper, authsims.RandomGenesisAccounts, nil) bankModule := bank.NewAppModule(cdc, bankKeeper, accountKeeper) - stakingModule := staking.NewAppModule(cdc, stakingKeeper, accountKeeper, bankKeeper) + stakingModule := staking.NewAppModule(cdc, stakingKeeper) consensusModule := consensus.NewAppModule(cdc, consensusParamsKeeper) integrationApp := integration.NewIntegrationApp(newCtx, logger, keys, cdc, diff --git a/tests/integration/staking/keeper/deterministic_test.go b/tests/integration/staking/keeper/deterministic_test.go index ca5f1047808d..4b9afd591281 100644 --- a/tests/integration/staking/keeper/deterministic_test.go +++ b/tests/integration/staking/keeper/deterministic_test.go @@ -2,6 +2,8 @@ package keeper_test import ( "context" + "fmt" + "net/url" "testing" "time" @@ -133,7 +135,7 @@ func initDeterministicFixture(t *testing.T) *deterministicFixture { authModule := auth.NewAppModule(cdc, accountKeeper, acctsModKeeper, authsims.RandomGenesisAccounts, nil) bankModule := bank.NewAppModule(cdc, bankKeeper, accountKeeper) - stakingModule := staking.NewAppModule(cdc, stakingKeeper, accountKeeper, bankKeeper) + stakingModule := staking.NewAppModule(cdc, stakingKeeper) consensusModule := consensus.NewAppModule(cdc, consensusParamsKeeper) integrationApp := integration.NewIntegrationApp(newCtx, logger, keys, cdc, @@ -214,6 +216,26 @@ func bondTypeGenerator() *rapid.Generator[stakingtypes.BondStatus] { }) } +func metadataGenerator() *rapid.Generator[stakingtypes.Metadata] { + return rapid.Custom(func(t *rapid.T) stakingtypes.Metadata { + return stakingtypes.Metadata{ + ProfilePicUri: generateUri(t), + SocialHandleUris: []string{generateUri(t), generateUri(t)}, + } + }) +} + +func generateUri(t *rapid.T) string { + host := fmt.Sprintf("%s.com", rapid.StringN(5, 250, 255).Draw(t, "host")) + path := rapid.StringN(5, 250, 255).Draw(t, "path") + uri := url.URL{ + Scheme: "https", + Host: host, + Path: path, + } + return uri.String() +} + // createValidator creates a validator with random values. func createValidator(t *testing.T, rt *rapid.T, _ *deterministicFixture) stakingtypes.Validator { t.Helper() @@ -233,6 +255,7 @@ func createValidator(t *testing.T, rt *rapid.T, _ *deterministicFixture) staking rapid.StringN(5, 250, 255).Draw(rt, "website"), rapid.StringN(5, 250, 255).Draw(rt, "securityContact"), rapid.StringN(5, 250, 255).Draw(rt, "details"), + metadataGenerator().Draw(rt, "metadata"), ), UnbondingHeight: rapid.Int64Min(1).Draw(rt, "unbonding-height"), UnbondingTime: time.Now().Add(durationGenerator().Draw(rt, "duration")), @@ -308,6 +331,7 @@ func getStaticValidator(t *testing.T, f *deterministicFixture) stakingtypes.Vali "website", "securityContact", "details", + stakingtypes.Metadata{}, ), UnbondingHeight: 10, UnbondingTime: time.Date(2022, 10, 1, 0, 0, 0, 0, time.UTC), @@ -343,6 +367,7 @@ func getStaticValidator2(t *testing.T, f *deterministicFixture) stakingtypes.Val "website", "securityContact", "details", + stakingtypes.Metadata{}, ), UnbondingHeight: 100132, UnbondingTime: time.Date(2025, 10, 1, 0, 0, 0, 0, time.UTC), @@ -408,7 +433,7 @@ func TestGRPCValidator(t *testing.T) { ValidatorAddr: val.OperatorAddress, } - testdata.DeterministicIterations(t, f.ctx, req, f.queryClient.Validator, 1915, false) + testdata.DeterministicIterations(t, f.ctx, req, f.queryClient.Validator, 1921, false) } func TestGRPCValidators(t *testing.T) { @@ -434,7 +459,7 @@ func TestGRPCValidators(t *testing.T) { getStaticValidator(t, f) getStaticValidator2(t, f) - testdata.DeterministicIterations(t, f.ctx, &stakingtypes.QueryValidatorsRequest{}, f.queryClient.Validators, 2862, false) + testdata.DeterministicIterations(t, f.ctx, &stakingtypes.QueryValidatorsRequest{}, f.queryClient.Validators, 2880, false) } func TestGRPCValidatorDelegations(t *testing.T) { @@ -479,7 +504,7 @@ func TestGRPCValidatorDelegations(t *testing.T) { ValidatorAddr: validator.OperatorAddress, } - testdata.DeterministicIterations(t, f.ctx, req, f.queryClient.ValidatorDelegations, 14610, false) + testdata.DeterministicIterations(t, f.ctx, req, f.queryClient.ValidatorDelegations, 14628, false) } func TestGRPCValidatorUnbondingDelegations(t *testing.T) { @@ -569,7 +594,7 @@ func TestGRPCDelegation(t *testing.T) { DelegatorAddr: delegator1, } - testdata.DeterministicIterations(t, f.ctx, req, f.queryClient.Delegation, 4680, false) + testdata.DeterministicIterations(t, f.ctx, req, f.queryClient.Delegation, 4686, false) } func TestGRPCUnbondingDelegation(t *testing.T) { @@ -652,7 +677,7 @@ func TestGRPCDelegatorDelegations(t *testing.T) { DelegatorAddr: delegator1, } - testdata.DeterministicIterations(t, f.ctx, req, f.queryClient.DelegatorDelegations, 4283, false) + testdata.DeterministicIterations(t, f.ctx, req, f.queryClient.DelegatorDelegations, 4289, false) } func TestGRPCDelegatorValidator(t *testing.T) { @@ -690,7 +715,7 @@ func TestGRPCDelegatorValidator(t *testing.T) { ValidatorAddr: validator.OperatorAddress, } - testdata.DeterministicIterations(t, f.ctx, req, f.queryClient.DelegatorValidator, 3563, false) + testdata.DeterministicIterations(t, f.ctx, req, f.queryClient.DelegatorValidator, 3569, false) } func TestGRPCDelegatorUnbondingDelegations(t *testing.T) { @@ -772,7 +797,7 @@ func TestGRPCDelegatorValidators(t *testing.T) { assert.NilError(t, err) req := &stakingtypes.QueryDelegatorValidatorsRequest{DelegatorAddr: delegator1} - testdata.DeterministicIterations(t, f.ctx, req, f.queryClient.DelegatorValidators, 3166, false) + testdata.DeterministicIterations(t, f.ctx, req, f.queryClient.DelegatorValidators, 3172, false) } func TestGRPCPool(t *testing.T) { @@ -856,7 +881,7 @@ func TestGRPCRedelegations(t *testing.T) { DstValidatorAddr: validator2, } - testdata.DeterministicIterations(t, f.ctx, req, f.queryClient.Redelegations, 3920, false) + testdata.DeterministicIterations(t, f.ctx, req, f.queryClient.Redelegations, 3926, false) } func TestGRPCParams(t *testing.T) { diff --git a/tests/integration/staking/keeper/genesis_test.go b/tests/integration/staking/keeper/genesis_test.go index 95e34da18485..da9fd6c5d660 100644 --- a/tests/integration/staking/keeper/genesis_test.go +++ b/tests/integration/staking/keeper/genesis_test.go @@ -41,7 +41,7 @@ func TestInitGenesis(t *testing.T) { Status: types.Bonded, Tokens: valTokens, DelegatorShares: math.LegacyNewDecFromInt(valTokens), - Description: types.NewDescription("hoop", "", "", "", ""), + Description: types.NewDescription("hoop", "", "", "", "", types.Metadata{}), } assert.NilError(t, f.stakingKeeper.SetValidator(f.sdkCtx, bondedVal)) @@ -67,7 +67,7 @@ func TestInitGenesis(t *testing.T) { Status: types.Bonded, Tokens: valTokens, DelegatorShares: math.LegacyNewDecFromInt(valTokens), - Description: types.NewDescription("hoop", "", "", "", ""), + Description: types.NewDescription("hoop", "", "", "", "", types.Metadata{}), } bondedVal2 := types.Validator{ OperatorAddress: sdk.ValAddress(addrs[2]).String(), @@ -75,7 +75,7 @@ func TestInitGenesis(t *testing.T) { Status: types.Bonded, Tokens: valTokens, DelegatorShares: math.LegacyNewDecFromInt(valTokens), - Description: types.NewDescription("bloop", "", "", "", ""), + Description: types.NewDescription("bloop", "", "", "", "", types.Metadata{}), } // append new bonded validators to the list @@ -148,7 +148,7 @@ func TestInitGenesis_PoolsBalanceMismatch(t *testing.T) { Jailed: false, Tokens: math.NewInt(10), DelegatorShares: math.LegacyNewDecFromInt(math.NewInt(10)), - Description: types.NewDescription("bloop", "", "", "", ""), + Description: types.NewDescription("bloop", "", "", "", "", types.Metadata{}), } params := types.Params{ @@ -195,7 +195,7 @@ func TestInitGenesisLargeValidatorSet(t *testing.T) { validators[i], err = types.NewValidator( sdk.ValAddress(addrs[i]).String(), PKs[i], - types.NewDescription(fmt.Sprintf("#%d", i), "", "", "", ""), + types.NewDescription(fmt.Sprintf("#%d", i), "", "", "", "", types.Metadata{}), ) assert.NilError(t, err) validators[i].Status = types.Bonded diff --git a/tests/integration/staking/keeper/msg_server_test.go b/tests/integration/staking/keeper/msg_server_test.go index f5e4accc0073..f07308591a84 100644 --- a/tests/integration/staking/keeper/msg_server_test.go +++ b/tests/integration/staking/keeper/msg_server_test.go @@ -44,7 +44,7 @@ func TestCancelUnbondingDelegation(t *testing.T) { delegatorAddr := addrs[1] // setup a new validator with bonded status - validator, err := types.NewValidator(valAddr.String(), PKs[0], types.NewDescription("Validator", "", "", "", "")) + validator, err := types.NewValidator(valAddr.String(), PKs[0], types.NewDescription("Validator", "", "", "", "", types.Metadata{})) validator.Status = types.Bonded assert.NilError(t, err) assert.NilError(t, f.stakingKeeper.SetValidator(ctx, validator)) @@ -163,8 +163,6 @@ func TestCancelUnbondingDelegation(t *testing.T) { } for _, tc := range testCases { - tc := tc - t.Run(tc.name, func(t *testing.T) { _, err := msgServer.CancelUnbondingDelegation(ctx, &tc.req) if tc.exceptErr { diff --git a/tests/integration/staking/simulation/operations_test.go b/tests/integration/staking/simulation/operations_test.go deleted file mode 100644 index a5a6fbc41e14..000000000000 --- a/tests/integration/staking/simulation/operations_test.go +++ /dev/null @@ -1,443 +0,0 @@ -package simulation_test - -import ( - "math/big" - "math/rand" - "testing" - "time" - - abci "github.com/cometbft/cometbft/api/cometbft/abci/v1" - cmttypes "github.com/cometbft/cometbft/types" - "github.com/cosmos/gogoproto/proto" - "github.com/stretchr/testify/require" - "github.com/stretchr/testify/suite" - - "cosmossdk.io/collections" - "cosmossdk.io/core/header" - "cosmossdk.io/depinject" - sdklog "cosmossdk.io/log" - "cosmossdk.io/math" - bankkeeper "cosmossdk.io/x/bank/keeper" - banktestutil "cosmossdk.io/x/bank/testutil" - distrkeeper "cosmossdk.io/x/distribution/keeper" - distrtypes "cosmossdk.io/x/distribution/types" - mintkeeper "cosmossdk.io/x/mint/keeper" - minttypes "cosmossdk.io/x/mint/types" - stakingkeeper "cosmossdk.io/x/staking/keeper" - "cosmossdk.io/x/staking/simulation" - "cosmossdk.io/x/staking/testutil" - "cosmossdk.io/x/staking/types" - - "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/codec/address" - cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" - "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" - "github.com/cosmos/cosmos-sdk/runtime" - "github.com/cosmos/cosmos-sdk/tests/integration/staking" - simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" - sdk "github.com/cosmos/cosmos-sdk/types" - moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil" - simtypes "github.com/cosmos/cosmos-sdk/types/simulation" - authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper" - authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" -) - -type SimTestSuite struct { - suite.Suite - - r *rand.Rand - txConfig client.TxConfig - accounts []simtypes.Account - ctx sdk.Context - app *runtime.App - bankKeeper bankkeeper.Keeper - accountKeeper authkeeper.AccountKeeper - distrKeeper distrkeeper.Keeper - stakingKeeper *stakingkeeper.Keeper - - encCfg moduletestutil.TestEncodingConfig -} - -func (s *SimTestSuite) SetupTest() { - sdk.DefaultPowerReduction = math.NewIntFromBigInt(new(big.Int).Exp(big.NewInt(10), big.NewInt(18), nil)) - - s.r = rand.New(rand.NewSource(1)) - accounts := simtypes.RandomAccounts(s.r, 4) - - // create genesis accounts - senderPrivKey := secp256k1.GenPrivKey() - acc := authtypes.NewBaseAccount(senderPrivKey.PubKey().Address().Bytes(), senderPrivKey.PubKey(), 0, 0) - accs := []simtestutil.GenesisAccount{ - {GenesisAccount: acc, Coins: sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, math.NewInt(100000000000000)))}, - } - - // create validator set with single validator - account := accounts[0] - cmtPk, err := cryptocodec.ToCmtPubKeyInterface(account.ConsKey.PubKey()) - require.NoError(s.T(), err) - validator := cmttypes.NewValidator(cmtPk, 1) - - startupCfg := simtestutil.DefaultStartUpConfig() - startupCfg.GenesisAccounts = accs - startupCfg.ValidatorSet = func() (*cmttypes.ValidatorSet, error) { - return cmttypes.NewValidatorSet([]*cmttypes.Validator{validator}), nil - } - - var ( - accountKeeper authkeeper.AccountKeeper - mintKeeper mintkeeper.Keeper - bankKeeper bankkeeper.Keeper - distrKeeper distrkeeper.Keeper - stakingKeeper *stakingkeeper.Keeper - ) - - cfg := depinject.Configs( - staking.AppConfig, - depinject.Supply(sdklog.NewNopLogger()), - ) - - app, err := simtestutil.SetupWithConfiguration(cfg, startupCfg, &s.txConfig, &bankKeeper, &accountKeeper, &mintKeeper, &distrKeeper, &stakingKeeper) - require.NoError(s.T(), err) - - ctx := app.BaseApp.NewContext(false) - s.Require().NoError(mintKeeper.Params.Set(ctx, minttypes.DefaultParams())) - s.Require().NoError(mintKeeper.Minter.Set(ctx, minttypes.DefaultInitialMinter())) - - initAmt := stakingKeeper.TokensFromConsensusPower(ctx, 200) - initCoins := sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, initAmt)) - - s.accounts = accounts - // remove genesis validator account - // add coins to the accounts - for _, account := range accounts[1:] { - acc := accountKeeper.NewAccountWithAddress(ctx, account.Address) - accountKeeper.SetAccount(ctx, acc) - s.Require().NoError(banktestutil.FundAccount(ctx, bankKeeper, account.Address, initCoins)) - } - - s.accountKeeper = accountKeeper - s.bankKeeper = bankKeeper - s.distrKeeper = distrKeeper - s.stakingKeeper = stakingKeeper - s.ctx = ctx - s.app = app -} - -// TestWeightedOperations tests the weights of the operations. -func (s *SimTestSuite) TestWeightedOperations() { - require := s.Require() - - s.ctx.WithChainID("test-chain") - - cdc := s.encCfg.Codec - appParams := make(simtypes.AppParams) - - weightedOps := simulation.WeightedOperations(appParams, cdc, s.txConfig, s.accountKeeper, - s.bankKeeper, s.stakingKeeper, - ) - - expected := []struct { - weight int - opMsgRoute string - opMsgName string - }{ - {simulation.DefaultWeightMsgCreateValidator, types.ModuleName, sdk.MsgTypeURL(&types.MsgCreateValidator{})}, - {simulation.DefaultWeightMsgEditValidator, types.ModuleName, sdk.MsgTypeURL(&types.MsgEditValidator{})}, - {simulation.DefaultWeightMsgDelegate, types.ModuleName, sdk.MsgTypeURL(&types.MsgDelegate{})}, - {simulation.DefaultWeightMsgUndelegate, types.ModuleName, sdk.MsgTypeURL(&types.MsgUndelegate{})}, - {simulation.DefaultWeightMsgBeginRedelegate, types.ModuleName, sdk.MsgTypeURL(&types.MsgBeginRedelegate{})}, - {simulation.DefaultWeightMsgCancelUnbondingDelegation, types.ModuleName, sdk.MsgTypeURL(&types.MsgCancelUnbondingDelegation{})}, - {simulation.DefaultWeightMsgRotateConsPubKey, types.ModuleName, sdk.MsgTypeURL(&types.MsgRotateConsPubKey{})}, - } - - for i, w := range weightedOps { - operationMsg, _, _ := w.Op()(s.r, s.app.BaseApp, s.ctx, s.accounts, s.ctx.ChainID()) - // require.NoError(t, err) // TODO check if it should be NoError - - // the following checks are very much dependent from the ordering of the output given - // by WeightedOperations. if the ordering in WeightedOperations changes some tests - // will fail - require.Equal(expected[i].weight, w.Weight(), "weight should be the same") - require.Equal(expected[i].opMsgRoute, operationMsg.Route, "route should be the same") - require.Equal(expected[i].opMsgName, operationMsg.Name, "operation Msg name should be the same") - } -} - -// TestSimulateMsgCreateValidator tests the normal scenario of a valid message of type TypeMsgCreateValidator. -// Abonormal scenarios, where the message are created by an errors are not tested here. -func (s *SimTestSuite) TestSimulateMsgCreateValidator() { - require := s.Require() - _, err := s.app.FinalizeBlock(&abci.FinalizeBlockRequest{Height: s.app.LastBlockHeight() + 1, Hash: s.app.LastCommitID().Hash}) - require.NoError(err) - // execute operation - op := simulation.SimulateMsgCreateValidator(s.txConfig, s.accountKeeper, s.bankKeeper, s.stakingKeeper) - operationMsg, futureOperations, err := op(s.r, s.app.BaseApp, s.ctx, s.accounts[1:], "") - require.NoError(err) - - var msg types.MsgCreateValidator - err = proto.Unmarshal(operationMsg.Msg, &msg) - require.NoError(err) - require.True(operationMsg.OK) - require.Equal(sdk.MsgTypeURL(&types.MsgCreateValidator{}), sdk.MsgTypeURL(&msg)) - valaddr, err := sdk.ValAddressFromBech32(msg.ValidatorAddress) - require.NoError(err) - require.Equal("cosmos1p8wcgrjr4pjju90xg6u9cgq55dxwq8j7u4x9a0", sdk.AccAddress(valaddr).String()) - require.Equal("cosmosvaloper1p8wcgrjr4pjju90xg6u9cgq55dxwq8j7epjs3u", msg.ValidatorAddress) - require.Len(futureOperations, 0) -} - -// TestSimulateMsgCancelUnbondingDelegation tests the normal scenario of a valid message of type TypeMsgCancelUnbondingDelegation. -// Abonormal scenarios, where the message is -func (s *SimTestSuite) TestSimulateMsgCancelUnbondingDelegation() { - require := s.Require() - blockTime := time.Now().UTC() - ctx := s.ctx.WithHeaderInfo(header.Info{Time: blockTime}) - - // setup accounts[1] as validator - validator0 := s.getTestingValidator0(ctx) - - // setup delegation - delTokens := s.stakingKeeper.TokensFromConsensusPower(ctx, 2) - validator0, issuedShares := validator0.AddTokensFromDel(delTokens) - delegator := s.accounts[2] - delegation := types.NewDelegation(delegator.Address.String(), validator0.GetOperator(), issuedShares) - require.NoError(s.stakingKeeper.SetDelegation(ctx, delegation)) - val0bz, err := s.stakingKeeper.ValidatorAddressCodec().StringToBytes(validator0.GetOperator()) - s.Require().NoError(err) - s.Require().NoError(s.distrKeeper.DelegatorStartingInfo.Set(ctx, collections.Join(sdk.ValAddress(val0bz), delegator.Address), distrtypes.NewDelegatorStartingInfo(2, math.LegacyOneDec(), 200))) - - s.setupValidatorRewards(ctx, val0bz) - - // unbonding delegation - udb := types.NewUnbondingDelegation(delegator.Address, val0bz, s.app.LastBlockHeight()+1, blockTime.Add(2*time.Minute), delTokens, 0, address.NewBech32Codec("cosmosvaloper"), address.NewBech32Codec("cosmos")) - require.NoError(s.stakingKeeper.SetUnbondingDelegation(ctx, udb)) - s.setupValidatorRewards(ctx, val0bz) - - _, err = s.app.FinalizeBlock(&abci.FinalizeBlockRequest{Height: s.app.LastBlockHeight() + 1, Hash: s.app.LastCommitID().Hash, Time: blockTime}) - require.NoError(err) - // execute operation - op := simulation.SimulateMsgCancelUnbondingDelegate(s.txConfig, s.accountKeeper, s.bankKeeper, s.stakingKeeper) - accounts := []simtypes.Account{delegator} - operationMsg, futureOperations, err := op(s.r, s.app.BaseApp, ctx, accounts, "") - require.NoError(err) - - var msg types.MsgCancelUnbondingDelegation - err = proto.Unmarshal(operationMsg.Msg, &msg) - require.NoError(err) - require.True(operationMsg.OK) - require.Equal(sdk.MsgTypeURL(&types.MsgCancelUnbondingDelegation{}), sdk.MsgTypeURL(&msg)) - require.Equal(delegator.Address.String(), msg.DelegatorAddress) - require.Equal(validator0.GetOperator(), msg.ValidatorAddress) - require.Len(futureOperations, 0) -} - -// TestSimulateMsgEditValidator tests the normal scenario of a valid message of type TypeMsgEditValidator. -// Abonormal scenarios, where the message is created by an errors are not tested here. -func (s *SimTestSuite) TestSimulateMsgEditValidator() { - require := s.Require() - blockTime := time.Now().UTC() - ctx := s.ctx.WithHeaderInfo(header.Info{Time: blockTime}) - - // setup accounts[0] as validator - _ = s.getTestingValidator0(ctx) - - _, err := s.app.FinalizeBlock(&abci.FinalizeBlockRequest{Height: s.app.LastBlockHeight() + 1, Hash: s.app.LastCommitID().Hash, Time: blockTime}) - require.NoError(err) - // execute operation - op := simulation.SimulateMsgEditValidator(s.txConfig, s.accountKeeper, s.bankKeeper, s.stakingKeeper) - operationMsg, futureOperations, err := op(s.r, s.app.BaseApp, ctx, s.accounts, "") - require.NoError(err) - - var msg types.MsgEditValidator - err = proto.Unmarshal(operationMsg.Msg, &msg) - require.NoError(err) - require.True(operationMsg.OK) - require.Equal(sdk.MsgTypeURL(&types.MsgEditValidator{}), sdk.MsgTypeURL(&msg)) - require.Equal("cosmosvaloper1p8wcgrjr4pjju90xg6u9cgq55dxwq8j7epjs3u", msg.ValidatorAddress) - require.Len(futureOperations, 0) -} - -// TestSimulateMsgDelegate tests the normal scenario of a valid message of type TypeMsgDelegate. -// Abonormal scenarios, where the message is created by an errors are not tested here. -func (s *SimTestSuite) TestSimulateMsgDelegate() { - require := s.Require() - blockTime := time.Now().UTC() - ctx := s.ctx.WithHeaderInfo(header.Info{Time: blockTime}) - - // execute operation - op := simulation.SimulateMsgDelegate(s.txConfig, s.accountKeeper, s.bankKeeper, s.stakingKeeper) - operationMsg, futureOperations, err := op(s.r, s.app.BaseApp, ctx, s.accounts[1:], "") - require.NoError(err) - - var msg types.MsgDelegate - err = proto.Unmarshal(operationMsg.Msg, &msg) - require.NoError(err) - require.True(operationMsg.OK) - require.Equal("cosmos1p8wcgrjr4pjju90xg6u9cgq55dxwq8j7u4x9a0", msg.DelegatorAddress) - require.Equal("stake", msg.Amount.Denom) - require.Equal(sdk.MsgTypeURL(&types.MsgDelegate{}), sdk.MsgTypeURL(&msg)) - require.Equal("cosmosvaloper122js6qry7nlgp63gcse8muknspuxur77vj3kkr", msg.ValidatorAddress) - require.Len(futureOperations, 0) -} - -// TestSimulateMsgUndelegate tests the normal scenario of a valid message of type TypeMsgUndelegate. -// Abonormal scenarios, where the message is created by an errors are not tested here. -func (s *SimTestSuite) TestSimulateMsgUndelegate() { - require := s.Require() - blockTime := time.Now().UTC() - ctx := s.ctx.WithHeaderInfo(header.Info{Time: blockTime}) - - // setup accounts[1] as validator - validator0 := s.getTestingValidator0(ctx) - - // setup delegation - delTokens := s.stakingKeeper.TokensFromConsensusPower(ctx, 2) - validator0, issuedShares := validator0.AddTokensFromDel(delTokens) - delegator := s.accounts[2] - delegation := types.NewDelegation(delegator.Address.String(), validator0.GetOperator(), issuedShares) - require.NoError(s.stakingKeeper.SetDelegation(ctx, delegation)) - val0bz, err := s.stakingKeeper.ValidatorAddressCodec().StringToBytes(validator0.GetOperator()) - s.Require().NoError(err) - s.Require().NoError(s.distrKeeper.DelegatorStartingInfo.Set(ctx, collections.Join(sdk.ValAddress(val0bz), delegator.Address), distrtypes.NewDelegatorStartingInfo(2, math.LegacyOneDec(), 200))) - - s.setupValidatorRewards(ctx, val0bz) - - _, err = s.app.FinalizeBlock(&abci.FinalizeBlockRequest{Height: s.app.LastBlockHeight() + 1, Hash: s.app.LastCommitID().Hash, Time: blockTime}) - require.NoError(err) - // execute operation - op := simulation.SimulateMsgUndelegate(s.txConfig, s.accountKeeper, s.bankKeeper, s.stakingKeeper) - operationMsg, futureOperations, err := op(s.r, s.app.BaseApp, ctx, s.accounts, "") - require.NoError(err) - - var msg types.MsgUndelegate - err = proto.Unmarshal(operationMsg.Msg, &msg) - require.NoError(err) - require.True(operationMsg.OK) - require.Equal("cosmos1ghekyjucln7y67ntx7cf27m9dpuxxemn4c8g4r", msg.DelegatorAddress) - require.Equal("1646627814093010272", msg.Amount.Amount.String()) - require.Equal("stake", msg.Amount.Denom) - require.Equal(sdk.MsgTypeURL(&types.MsgUndelegate{}), sdk.MsgTypeURL(&msg)) - require.Equal("cosmosvaloper1p8wcgrjr4pjju90xg6u9cgq55dxwq8j7epjs3u", msg.ValidatorAddress) - require.Len(futureOperations, 0) -} - -// TestSimulateMsgBeginRedelegate tests the normal scenario of a valid message of type TypeMsgBeginRedelegate. -// Abonormal scenarios, where the message is created by an errors, are not tested here. -func (s *SimTestSuite) TestSimulateMsgBeginRedelegate() { - require := s.Require() - blockTime := time.Now().UTC() - ctx := s.ctx.WithHeaderInfo(header.Info{Time: blockTime}) - - // setup accounts[1] as validator0 and accounts[2] as validator1 - validator0 := s.getTestingValidator0(ctx) - validator1 := s.getTestingValidator1(ctx) - - delTokens := s.stakingKeeper.TokensFromConsensusPower(ctx, 2) - validator1, issuedShares := validator1.AddTokensFromDel(delTokens) - - // setup accounts[3] as delegator - delegator := s.accounts[3] - delegation := types.NewDelegation(delegator.Address.String(), validator0.GetOperator(), issuedShares) - require.NoError(s.stakingKeeper.SetDelegation(ctx, delegation)) - val0bz, err := s.stakingKeeper.ValidatorAddressCodec().StringToBytes(validator0.GetOperator()) - s.Require().NoError(err) - val1bz, err := s.stakingKeeper.ValidatorAddressCodec().StringToBytes(validator1.GetOperator()) - s.Require().NoError(err) - s.Require().NoError(s.distrKeeper.DelegatorStartingInfo.Set(ctx, collections.Join(sdk.ValAddress(val0bz), delegator.Address), distrtypes.NewDelegatorStartingInfo(2, math.LegacyOneDec(), 200))) - - s.setupValidatorRewards(ctx, val0bz) - s.setupValidatorRewards(ctx, val1bz) - - _, err = s.app.FinalizeBlock(&abci.FinalizeBlockRequest{Height: s.app.LastBlockHeight() + 1, Hash: s.app.LastCommitID().Hash, Time: blockTime}) - require.NoError(err) - - // execute operation - op := simulation.SimulateMsgBeginRedelegate(s.txConfig, s.accountKeeper, s.bankKeeper, s.stakingKeeper) - operationMsg, futureOperations, err := op(s.r, s.app.BaseApp, ctx, s.accounts, "") - s.T().Logf("operation message: %v", operationMsg) - require.NoError(err) - - var msg types.MsgBeginRedelegate - err = proto.Unmarshal(operationMsg.Msg, &msg) - require.NoError(err) - require.True(operationMsg.OK) - require.Equal("cosmos1ua0fwyws7vzjrry3pqkklvf8mny93l9s9zg0h4", msg.DelegatorAddress) - require.Equal("stake", msg.Amount.Denom) - require.Equal(sdk.MsgTypeURL(&types.MsgBeginRedelegate{}), sdk.MsgTypeURL(&msg)) - require.Equal("cosmosvaloper1ghekyjucln7y67ntx7cf27m9dpuxxemnsvnaes", msg.ValidatorDstAddress) - require.Equal("cosmosvaloper1p8wcgrjr4pjju90xg6u9cgq55dxwq8j7epjs3u", msg.ValidatorSrcAddress) - require.Len(futureOperations, 0) -} - -func (s *SimTestSuite) TestSimulateRotateConsPubKey() { - require := s.Require() - blockTime := time.Now().UTC() - ctx := s.ctx.WithHeaderInfo(header.Info{Time: blockTime}) - - _ = s.getTestingValidator2(ctx) - - // begin a new block - _, err := s.app.FinalizeBlock(&abci.FinalizeBlockRequest{Height: s.app.LastBlockHeight() + 1, Hash: s.app.LastCommitID().Hash, Time: blockTime}) - require.NoError(err) - - // execute operation - op := simulation.SimulateMsgRotateConsPubKey(s.txConfig, s.accountKeeper, s.bankKeeper, s.stakingKeeper) - operationMsg, futureOperations, err := op(s.r, s.app.BaseApp, ctx, s.accounts, "") - require.NoError(err) - - var msg types.MsgRotateConsPubKey - err = proto.Unmarshal(operationMsg.Msg, &msg) - require.NoError(err) - - require.True(operationMsg.OK) - require.Equal(sdk.MsgTypeURL(&types.MsgRotateConsPubKey{}), sdk.MsgTypeURL(&msg)) - require.Equal("cosmosvaloper1p8wcgrjr4pjju90xg6u9cgq55dxwq8j7epjs3u", msg.ValidatorAddress) - require.Len(futureOperations, 0) -} - -func (s *SimTestSuite) getTestingValidator0(ctx sdk.Context) types.Validator { - commission0 := types.NewCommission(math.LegacyZeroDec(), math.LegacyOneDec(), math.LegacyOneDec()) - return s.getTestingValidator(ctx, commission0, 1) -} - -func (s *SimTestSuite) getTestingValidator1(ctx sdk.Context) types.Validator { - commission1 := types.NewCommission(math.LegacyZeroDec(), math.LegacyZeroDec(), math.LegacyZeroDec()) - return s.getTestingValidator(ctx, commission1, 2) -} - -func (s *SimTestSuite) getTestingValidator(ctx sdk.Context, commission types.Commission, n int) types.Validator { - account := s.accounts[n] - valPubKey := account.PubKey - valAddr := sdk.ValAddress(account.PubKey.Address().Bytes()) - validator := testutil.NewValidator(s.T(), valAddr, valPubKey) - validator, err := validator.SetInitialCommission(commission) - s.Require().NoError(err) - - validator.DelegatorShares = math.LegacyNewDec(100) - validator.Tokens = s.stakingKeeper.TokensFromConsensusPower(ctx, 100) - - s.Require().NoError(s.stakingKeeper.SetValidator(ctx, validator)) - - return validator -} - -func (s *SimTestSuite) getTestingValidator2(ctx sdk.Context) types.Validator { - val := s.getTestingValidator0(ctx) - val.Status = types.Bonded - s.Require().NoError(s.stakingKeeper.SetValidator(ctx, val)) - s.Require().NoError(s.stakingKeeper.SetValidatorByConsAddr(ctx, val)) - return val -} - -func (s *SimTestSuite) setupValidatorRewards(ctx sdk.Context, valAddress sdk.ValAddress) { - decCoins := sdk.DecCoins{sdk.NewDecCoinFromDec(sdk.DefaultBondDenom, math.LegacyOneDec())} - historicalRewards := distrtypes.NewValidatorHistoricalRewards(decCoins, 2) - s.Require().NoError(s.distrKeeper.ValidatorHistoricalRewards.Set(ctx, collections.Join(valAddress, uint64(2)), historicalRewards)) - // setup current revards - currentRewards := distrtypes.NewValidatorCurrentRewards(decCoins, 3) - s.Require().NoError(s.distrKeeper.ValidatorCurrentRewards.Set(ctx, valAddress, currentRewards)) -} - -func TestSimTestSuite(t *testing.T) { - suite.Run(t, new(SimTestSuite)) -} diff --git a/tests/integration/tx/aminojson/aminojson_test.go b/tests/integration/tx/aminojson/aminojson_test.go index ec218ca47da3..cf9695b4b451 100644 --- a/tests/integration/tx/aminojson/aminojson_test.go +++ b/tests/integration/tx/aminojson/aminojson_test.go @@ -1,10 +1,9 @@ package aminojson import ( - "context" + "bytes" "fmt" - "reflect" - "strings" + stdmath "math" "testing" "time" @@ -12,26 +11,12 @@ import ( gogoproto "github.com/cosmos/gogoproto/proto" "github.com/stretchr/testify/require" "google.golang.org/protobuf/proto" - "google.golang.org/protobuf/types/known/anypb" - "google.golang.org/protobuf/types/known/durationpb" - "google.golang.org/protobuf/types/known/timestamppb" "pgregory.net/rapid" authapi "cosmossdk.io/api/cosmos/auth/v1beta1" - authzapi "cosmossdk.io/api/cosmos/authz/v1beta1" bankapi "cosmossdk.io/api/cosmos/bank/v1beta1" v1beta1 "cosmossdk.io/api/cosmos/base/v1beta1" - "cosmossdk.io/api/cosmos/crypto/ed25519" - multisigapi "cosmossdk.io/api/cosmos/crypto/multisig" - "cosmossdk.io/api/cosmos/crypto/secp256k1" - distapi "cosmossdk.io/api/cosmos/distribution/v1beta1" - gov_v1_api "cosmossdk.io/api/cosmos/gov/v1" - gov_v1beta1_api "cosmossdk.io/api/cosmos/gov/v1beta1" msgv1 "cosmossdk.io/api/cosmos/msg/v1" - slashingapi "cosmossdk.io/api/cosmos/slashing/v1beta1" - stakingapi "cosmossdk.io/api/cosmos/staking/v1beta1" - txv1beta1 "cosmossdk.io/api/cosmos/tx/v1beta1" - vestingapi "cosmossdk.io/api/cosmos/vesting/v1beta1" "cosmossdk.io/math" authztypes "cosmossdk.io/x/authz" authzmodule "cosmossdk.io/x/authz/module" @@ -52,7 +37,6 @@ import ( "cosmossdk.io/x/staking" stakingtypes "cosmossdk.io/x/staking/types" "cosmossdk.io/x/tx/signing/aminojson" - signing_testutil "cosmossdk.io/x/tx/signing/testutil" "cosmossdk.io/x/upgrade" codectestutil "github.com/cosmos/cosmos-sdk/codec/testutil" @@ -61,17 +45,13 @@ import ( "github.com/cosmos/cosmos-sdk/crypto/keys/multisig" secp256k1types "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" "github.com/cosmos/cosmos-sdk/tests/integration/rapidgen" + "github.com/cosmos/cosmos-sdk/tests/integration/tx/internal" gogo_testpb "github.com/cosmos/cosmos-sdk/tests/integration/tx/internal/gogo/testpb" - pulsar_testpb "github.com/cosmos/cosmos-sdk/tests/integration/tx/internal/pulsar/testpb" "github.com/cosmos/cosmos-sdk/testutil/testdata" "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/bech32" "github.com/cosmos/cosmos-sdk/types/module/testutil" - signingtypes "github.com/cosmos/cosmos-sdk/types/tx/signing" "github.com/cosmos/cosmos-sdk/x/auth" - "github.com/cosmos/cosmos-sdk/x/auth/migrations/legacytx" - "github.com/cosmos/cosmos-sdk/x/auth/signing" - "github.com/cosmos/cosmos-sdk/x/auth/tx" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" "github.com/cosmos/cosmos-sdk/x/auth/vesting" vestingtypes "github.com/cosmos/cosmos-sdk/x/auth/vesting/types" @@ -92,13 +72,23 @@ import ( // In order for step 3 to work certain restrictions on the data generated in step 1 must be enforced and are described // by the mutation of genOpts passed to the generator. func TestAminoJSON_Equivalence(t *testing.T) { - encCfg := testutil.MakeTestEncodingConfig( - codectestutil.CodecOptions{}, auth.AppModule{}, authzmodule.AppModule{}, bank.AppModule{}, - consensus.AppModule{}, distribution.AppModule{}, evidence.AppModule{}, feegrantmodule.AppModule{}, - gov.AppModule{}, groupmodule.AppModule{}, mint.AppModule{}, - slashing.AppModule{}, staking.AppModule{}, upgrade.AppModule{}, vesting.AppModule{}) - legacytx.RegressionTestingAminoCodec = encCfg.Amino - aj := aminojson.NewEncoder(aminojson.EncoderOptions{DoNotSortFields: true}) + fixture := internal.NewSigningFixture(t, internal.SigningFixtureOptions{}, + auth.AppModule{}, + authzmodule.AppModule{}, + bank.AppModule{}, + consensus.AppModule{}, + distribution.AppModule{}, + evidence.AppModule{}, + feegrantmodule.AppModule{}, + gov.AppModule{}, + groupmodule.AppModule{}, + mint.AppModule{}, + slashing.AppModule{}, + staking.AppModule{}, + upgrade.AppModule{}, + vesting.AppModule{}, + ) + aj := aminojson.NewEncoder(aminojson.EncoderOptions{}) for _, tt := range rapidgen.DefaultGeneratedTypes { desc := tt.Pulsar.ProtoReflect().Descriptor() @@ -106,7 +96,7 @@ func TestAminoJSON_Equivalence(t *testing.T) { t.Run(name, func(t *testing.T) { gen := rapidproto.MessageGenerator(tt.Pulsar, tt.Opts) fmt.Printf("testing %s\n", tt.Pulsar.ProtoReflect().Descriptor().FullName()) - rapid.Check(t, func(t *rapid.T) { + rapid.Check(t, func(r *rapid.T) { // uncomment to debug; catch a panic and inspect application state // defer func() { // if r := recover(); r != nil { @@ -115,39 +105,28 @@ func TestAminoJSON_Equivalence(t *testing.T) { // } // }() - msg := gen.Draw(t, "msg") + msg := gen.Draw(r, "msg") postFixPulsarMessage(msg) - // txBuilder.GetTx will fail if the msg has no signers - // so it does not make sense to run these cases, apparently. - signers, err := encCfg.TxConfig.SigningContext().GetSigners(msg) - if len(signers) == 0 { - // skip - return - } - if err != nil { - if strings.Contains(err.Error(), "empty address string is not allowed") { - return - } - require.NoError(t, err) - } gogo := tt.Gogo sanity := tt.Pulsar protoBz, err := proto.Marshal(msg) - require.NoError(t, err) + require.NoError(r, err) err = proto.Unmarshal(protoBz, sanity) - require.NoError(t, err) + require.NoError(r, err) - err = encCfg.Codec.Unmarshal(protoBz, gogo) - require.NoError(t, err) + err = fixture.UnmarshalGogoProto(protoBz, gogo) + require.NoError(r, err) - legacyAminoJSON, err := encCfg.Amino.MarshalJSON(gogo) - require.NoError(t, err) + legacyAminoJSON := fixture.MarshalLegacyAminoJSON(t, gogo) aminoJSON, err := aj.Marshal(msg) - require.NoError(t, err) - require.Equal(t, string(legacyAminoJSON), string(aminoJSON)) + require.NoError(r, err) + if !bytes.Equal(legacyAminoJSON, aminoJSON) { + require.Failf(r, "JSON mismatch", "legacy: %s\n x/tx: %s\n", + string(legacyAminoJSON), string(aminoJSON)) + } // test amino json signer handler equivalence if !proto.HasExtension(desc.Options(), msgv1.E_Signer) { @@ -155,366 +134,240 @@ func TestAminoJSON_Equivalence(t *testing.T) { return } - handlerOptions := signing_testutil.HandlerArgumentOptions{ - ChainID: "test-chain", - Memo: "sometestmemo", - Msg: tt.Pulsar, - AccNum: 1, - AccSeq: 2, - SignerAddress: "signerAddress", - Fee: &txv1beta1.Fee{ - Amount: []*v1beta1.Coin{{Denom: "uatom", Amount: "1000"}}, - }, - } - - signerData, txData, err := signing_testutil.MakeHandlerArguments(handlerOptions) - require.NoError(t, err) - - handler := aminojson.NewSignModeHandler(aminojson.SignModeHandlerOptions{}) - signBz, err := handler.GetSignBytes(context.Background(), signerData, txData) - require.NoError(t, err) - - legacyHandler := tx.NewSignModeLegacyAminoJSONHandler() - txBuilder := encCfg.TxConfig.NewTxBuilder() - require.NoError(t, txBuilder.SetMsgs([]types.Msg{tt.Gogo}...)) - txBuilder.SetMemo(handlerOptions.Memo) - txBuilder.SetFeeAmount(types.Coins{types.NewInt64Coin("uatom", 1000)}) - theTx := txBuilder.GetTx() - - legacySigningData := signing.SignerData{ - ChainID: handlerOptions.ChainID, - Address: handlerOptions.SignerAddress, - AccountNumber: handlerOptions.AccNum, - Sequence: handlerOptions.AccSeq, - } - legacySignBz, err := legacyHandler.GetSignBytes(signingtypes.SignMode_SIGN_MODE_LEGACY_AMINO_JSON, - legacySigningData, theTx) - require.NoError(t, err) - require.Equal(t, string(legacySignBz), string(signBz)) + fixture.RequireLegacyAminoEquivalent(t, gogo) }) }) } } -func newAny(t *testing.T, msg proto.Message) *anypb.Any { - t.Helper() - bz, err := proto.Marshal(msg) - require.NoError(t, err) - typeName := fmt.Sprintf("/%s", msg.ProtoReflect().Descriptor().FullName()) - return &anypb.Any{ - TypeUrl: typeName, - Value: bz, - } -} - // TestAminoJSON_LegacyParity tests that the Encoder encoder produces the same output as the Encoder encoder. func TestAminoJSON_LegacyParity(t *testing.T) { - encCfg := testutil.MakeTestEncodingConfig(codectestutil.CodecOptions{}, auth.AppModule{}, authzmodule.AppModule{}, + fixture := internal.NewSigningFixture(t, internal.SigningFixtureOptions{}, + auth.AppModule{}, authzmodule.AppModule{}, bank.AppModule{}, distribution.AppModule{}, slashing.AppModule{}, staking.AppModule{}, vesting.AppModule{}, gov.AppModule{}) - legacytx.RegressionTestingAminoCodec = encCfg.Amino + aj := aminojson.NewEncoder(aminojson.EncoderOptions{}) - aj := aminojson.NewEncoder(aminojson.EncoderOptions{DoNotSortFields: true}) addr1 := types.AccAddress("addr1") now := time.Now() - genericAuth, _ := codectypes.NewAnyWithValue(&authztypes.GenericAuthorization{Msg: "foo"}) - genericAuthPulsar := newAny(t, &authzapi.GenericAuthorization{Msg: "foo"}) pubkeyAny, _ := codectypes.NewAnyWithValue(&secp256k1types.PubKey{Key: []byte("foo")}) - pubkeyAnyPulsar := newAny(t, &secp256k1.PubKey{Key: []byte("foo")}) - dec10bz, _ := math.LegacyNewDec(10).Marshal() - int123bz, _ := math.NewInt(123).Marshal() + dec5point4 := math.LegacyMustNewDecFromStr("5.4") + failingBaseAccount := authtypes.NewBaseAccountWithAddress(addr1) + failingBaseAccount.AccountNumber = stdmath.MaxUint64 cases := map[string]struct { - gogo gogoproto.Message - pulsar proto.Message - pulsarMarshalFails bool - - // this will fail in cases where a lossy encoding of an empty array to protobuf occurs. the unmarshalled bytes - // represent the array as nil, and a subsequent marshal to JSON represent the array as null instead of empty. - roundTripUnequal bool - - // pulsar does not support marshaling a math.Dec as anything except a string. Therefore, we cannot unmarshal - // a pulsar encoded Math.dec (the string representation of a Decimal) into a gogo Math.dec (expecting an int64). - protoUnmarshalFails bool + gogo gogoproto.Message + fails bool }{ - "auth/params": {gogo: &authtypes.Params{TxSigLimit: 10}, pulsar: &authapi.Params{TxSigLimit: 10}}, - "auth/module_account": { + "auth/params": { + gogo: &authtypes.Params{TxSigLimit: 10}, + }, + "auth/module_account_nil_permissions": { gogo: &authtypes.ModuleAccount{ - BaseAccount: authtypes.NewBaseAccountWithAddress(addr1), Permissions: []string{}, + BaseAccount: authtypes.NewBaseAccountWithAddress( + addr1, + ), }, - pulsar: &authapi.ModuleAccount{ - BaseAccount: &authapi.BaseAccount{Address: addr1.String()}, Permissions: []string{}, + }, + "auth/module_account/max_uint64": { + gogo: &authtypes.ModuleAccount{ + BaseAccount: failingBaseAccount, }, - roundTripUnequal: true, + fails: true, + }, + "auth/module_account_empty_permissions": { + gogo: &authtypes.ModuleAccount{ + BaseAccount: authtypes.NewBaseAccountWithAddress( + addr1, + ), + // empty set and nil are indistinguishable from the protoreflect API since they both + // marshal to zero proto bytes, there empty set is not supported. + Permissions: []string{}, + }, + fails: true, }, "auth/base_account": { - gogo: &authtypes.BaseAccount{Address: addr1.String(), PubKey: pubkeyAny}, - pulsar: &authapi.BaseAccount{Address: addr1.String(), PubKey: pubkeyAnyPulsar}, + gogo: &authtypes.BaseAccount{Address: addr1.String(), PubKey: pubkeyAny, AccountNumber: 1, Sequence: 2}, }, "authz/msg_grant": { gogo: &authztypes.MsgGrant{ + Granter: addr1.String(), Grantee: addr1.String(), Grant: authztypes.Grant{Expiration: &now, Authorization: genericAuth}, }, - pulsar: &authzapi.MsgGrant{ - Grant: &authzapi.Grant{Expiration: timestamppb.New(now), Authorization: genericAuthPulsar}, - }, }, "authz/msg_update_params": { - gogo: &authtypes.MsgUpdateParams{Params: authtypes.Params{TxSigLimit: 10}}, - pulsar: &authapi.MsgUpdateParams{Params: &authapi.Params{TxSigLimit: 10}}, + gogo: &authtypes.MsgUpdateParams{Params: authtypes.Params{TxSigLimit: 10}}, }, "authz/msg_exec/empty_msgs": { - gogo: &authztypes.MsgExec{Msgs: []*codectypes.Any{}}, - pulsar: &authzapi.MsgExec{Msgs: []*anypb.Any{}}, + gogo: &authztypes.MsgExec{Msgs: []*codectypes.Any{}}, }, "distribution/delegator_starting_info": { - gogo: &disttypes.DelegatorStartingInfo{}, - pulsar: &distapi.DelegatorStartingInfo{}, + gogo: &disttypes.DelegatorStartingInfo{Stake: math.LegacyNewDec(10)}, }, "distribution/delegator_starting_info/non_zero_dec": { - gogo: &disttypes.DelegatorStartingInfo{Stake: math.LegacyNewDec(10)}, - pulsar: &distapi.DelegatorStartingInfo{Stake: "10.000000000000000000"}, - protoUnmarshalFails: true, + gogo: &disttypes.DelegatorStartingInfo{Stake: math.LegacyNewDec(10)}, }, "distribution/delegation_delegator_reward": { - gogo: &disttypes.DelegationDelegatorReward{}, - pulsar: &distapi.DelegationDelegatorReward{}, + gogo: &disttypes.DelegationDelegatorReward{}, }, "distribution/msg_withdraw_delegator_reward": { - gogo: &disttypes.MsgWithdrawDelegatorReward{DelegatorAddress: "foo"}, - pulsar: &distapi.MsgWithdrawDelegatorReward{DelegatorAddress: "foo"}, + gogo: &disttypes.MsgWithdrawDelegatorReward{DelegatorAddress: "foo"}, }, "crypto/ed25519": { - gogo: &ed25519types.PubKey{Key: []byte("key")}, - pulsar: &ed25519.PubKey{Key: []byte("key")}, + gogo: &ed25519types.PubKey{Key: []byte("key")}, }, "crypto/secp256k1": { - gogo: &secp256k1types.PubKey{Key: []byte("key")}, - pulsar: &secp256k1.PubKey{Key: []byte("key")}, + gogo: &secp256k1types.PubKey{Key: []byte("key")}, }, "crypto/legacy_amino_pubkey": { - gogo: &multisig.LegacyAminoPubKey{PubKeys: []*codectypes.Any{pubkeyAny}}, - pulsar: &multisigapi.LegacyAminoPubKey{PublicKeys: []*anypb.Any{pubkeyAnyPulsar}}, + gogo: &multisig.LegacyAminoPubKey{PubKeys: []*codectypes.Any{pubkeyAny}}, }, - "crypto/legacy_amino_pubkey/empty": { - gogo: &multisig.LegacyAminoPubKey{}, - pulsar: &multisigapi.LegacyAminoPubKey{}, + "crypto/legacy_amino_pubkey_empty": { + gogo: &multisig.LegacyAminoPubKey{}, }, "consensus/evidence_params/duration": { - gogo: &gov_v1beta1_types.VotingParams{VotingPeriod: 1e9 + 7}, - pulsar: &gov_v1beta1_api.VotingParams{VotingPeriod: &durationpb.Duration{Seconds: 1, Nanos: 7}}, + gogo: &gov_v1beta1_types.VotingParams{VotingPeriod: 1e9 + 7}, }, "consensus/evidence_params/big_duration": { - gogo: &gov_v1beta1_types.VotingParams{VotingPeriod: time.Duration(rapidproto.MaxDurationSeconds*1e9) + 999999999}, - pulsar: &gov_v1beta1_api.VotingParams{VotingPeriod: &durationpb.Duration{ - Seconds: rapidproto.MaxDurationSeconds, Nanos: 999999999, - }}, + gogo: &gov_v1beta1_types.VotingParams{ + VotingPeriod: time.Duration(rapidproto.MaxDurationSeconds*1e9) + 999999999, + }, }, "consensus/evidence_params/too_big_duration": { - gogo: &gov_v1beta1_types.VotingParams{VotingPeriod: time.Duration(rapidproto.MaxDurationSeconds*1e9) + 999999999}, - pulsar: &gov_v1beta1_api.VotingParams{VotingPeriod: &durationpb.Duration{ - Seconds: rapidproto.MaxDurationSeconds + 1, Nanos: 999999999, - }}, - pulsarMarshalFails: true, + gogo: &gov_v1beta1_types.VotingParams{ + VotingPeriod: time.Duration(rapidproto.MaxDurationSeconds*1e9) + 999999999, + }, }, // amino.dont_omitempty + empty/nil lists produce some surprising results "bank/send_authorization/empty_coins": { - gogo: &banktypes.SendAuthorization{SpendLimit: []types.Coin{}}, - pulsar: &bankapi.SendAuthorization{SpendLimit: []*v1beta1.Coin{}}, + gogo: &banktypes.SendAuthorization{SpendLimit: []types.Coin{}}, }, "bank/send_authorization/nil_coins": { - gogo: &banktypes.SendAuthorization{SpendLimit: nil}, - pulsar: &bankapi.SendAuthorization{SpendLimit: nil}, + gogo: &banktypes.SendAuthorization{SpendLimit: nil}, }, "bank/send_authorization/empty_list": { - gogo: &banktypes.SendAuthorization{AllowList: []string{}}, - pulsar: &bankapi.SendAuthorization{AllowList: []string{}}, + gogo: &banktypes.SendAuthorization{AllowList: []string{}}, }, "bank/send_authorization/nil_list": { - gogo: &banktypes.SendAuthorization{AllowList: nil}, - pulsar: &bankapi.SendAuthorization{AllowList: nil}, + gogo: &banktypes.SendAuthorization{AllowList: nil}, }, "bank/msg_multi_send/nil_everything": { - gogo: &banktypes.MsgMultiSend{}, - pulsar: &bankapi.MsgMultiSend{}, + gogo: &banktypes.MsgMultiSend{}, }, "gov/v1_msg_submit_proposal": { - gogo: &gov_v1_types.MsgSubmitProposal{}, - pulsar: &gov_v1_api.MsgSubmitProposal{}, + gogo: &gov_v1_types.MsgSubmitProposal{}, }, - "slashing/params/empty_dec": { - gogo: &slashingtypes.Params{DowntimeJailDuration: 1e9 + 7}, - pulsar: &slashingapi.Params{DowntimeJailDuration: &durationpb.Duration{Seconds: 1, Nanos: 7}}, - }, - // This test cases demonstrates the expected contract and proper way to set a cosmos.Dec field represented - // as bytes in protobuf message, namely: - // dec10bz, _ := types.NewDec(10).Marshal() "slashing/params/dec": { gogo: &slashingtypes.Params{ - DowntimeJailDuration: 1e9 + 7, - MinSignedPerWindow: math.LegacyNewDec(10), - }, - pulsar: &slashingapi.Params{ - DowntimeJailDuration: &durationpb.Duration{Seconds: 1, Nanos: 7}, - MinSignedPerWindow: dec10bz, + DowntimeJailDuration: 1e9 + 7, + MinSignedPerWindow: math.LegacyNewDec(10), + SlashFractionDoubleSign: math.LegacyZeroDec(), + SlashFractionDowntime: math.LegacyZeroDec(), }, }, "staking/msg_update_params": { gogo: &stakingtypes.MsgUpdateParams{ Params: stakingtypes.Params{ - UnbondingTime: 0, - KeyRotationFee: types.Coin{}, - }, - }, - pulsar: &stakingapi.MsgUpdateParams{ - Params: &stakingapi.Params{ - UnbondingTime: &durationpb.Duration{Seconds: 0}, - KeyRotationFee: &v1beta1.Coin{}, + UnbondingTime: 0, + KeyRotationFee: types.Coin{}, + MinCommissionRate: math.LegacyZeroDec(), }, }, }, "staking/create_validator": { - gogo: &stakingtypes.MsgCreateValidator{Pubkey: pubkeyAny}, - pulsar: &stakingapi.MsgCreateValidator{ - Pubkey: pubkeyAnyPulsar, - Description: &stakingapi.Description{}, - Commission: &stakingapi.CommissionRates{}, - Value: &v1beta1.Coin{}, + gogo: &stakingtypes.MsgCreateValidator{ + Pubkey: pubkeyAny, + Commission: stakingtypes.CommissionRates{ + Rate: dec5point4, + MaxRate: math.LegacyZeroDec(), + MaxChangeRate: math.LegacyZeroDec(), + }, + MinSelfDelegation: math.NewIntFromUint64(10), }, }, "staking/msg_cancel_unbonding_delegation_response": { - gogo: &stakingtypes.MsgCancelUnbondingDelegationResponse{}, - pulsar: &stakingapi.MsgCancelUnbondingDelegationResponse{}, + gogo: &stakingtypes.MsgCancelUnbondingDelegationResponse{}, }, "staking/stake_authorization_empty": { - gogo: &stakingtypes.StakeAuthorization{}, - pulsar: &stakingapi.StakeAuthorization{}, + gogo: &stakingtypes.StakeAuthorization{}, }, "staking/stake_authorization_allow": { gogo: &stakingtypes.StakeAuthorization{ + MaxTokens: &types.Coin{Denom: "foo", Amount: math.NewInt(123)}, Validators: &stakingtypes.StakeAuthorization_AllowList{ - AllowList: &stakingtypes.StakeAuthorization_Validators{Address: []string{"foo"}}, + AllowList: &stakingtypes.StakeAuthorization_Validators{ + Address: []string{"foo"}, + }, }, + AuthorizationType: stakingtypes.AuthorizationType_AUTHORIZATION_TYPE_DELEGATE, }, - pulsar: &stakingapi.StakeAuthorization{ - Validators: &stakingapi.StakeAuthorization_AllowList{ - AllowList: &stakingapi.StakeAuthorization_Validators{Address: []string{"foo"}}, + }, + "staking/stake_authorization_deny": { + gogo: &stakingtypes.StakeAuthorization{ + MaxTokens: &types.Coin{Denom: "foo", Amount: math.NewInt(123)}, + Validators: &stakingtypes.StakeAuthorization_DenyList{ + DenyList: &stakingtypes.StakeAuthorization_Validators{}, }, + AuthorizationType: stakingtypes.AuthorizationType_AUTHORIZATION_TYPE_DELEGATE, }, + // to be fixed in https://github.com/cosmos/cosmos-sdk/pull/21782 + // TODO remove once merged + fails: true, }, "vesting/base_account_empty": { - gogo: &vestingtypes.BaseVestingAccount{BaseAccount: &authtypes.BaseAccount{}}, - pulsar: &vestingapi.BaseVestingAccount{BaseAccount: &authapi.BaseAccount{}}, + gogo: &vestingtypes.BaseVestingAccount{BaseAccount: &authtypes.BaseAccount{}}, }, "vesting/base_account_pubkey": { - gogo: &vestingtypes.BaseVestingAccount{BaseAccount: &authtypes.BaseAccount{PubKey: pubkeyAny}}, - pulsar: &vestingapi.BaseVestingAccount{BaseAccount: &authapi.BaseAccount{PubKey: pubkeyAnyPulsar}}, + gogo: &vestingtypes.BaseVestingAccount{ + BaseAccount: &authtypes.BaseAccount{PubKey: pubkeyAny}, + }, }, "math/int_as_string": { - gogo: &gogo_testpb.IntAsString{IntAsString: math.NewInt(123)}, - pulsar: &pulsar_testpb.IntAsString{IntAsString: "123"}, + gogo: &gogo_testpb.IntAsString{IntAsString: math.NewInt(123)}, }, "math/int_as_string/empty": { - gogo: &gogo_testpb.IntAsString{}, - pulsar: &pulsar_testpb.IntAsString{}, + gogo: &gogo_testpb.IntAsString{}, }, "math/int_as_bytes": { - gogo: &gogo_testpb.IntAsBytes{IntAsBytes: math.NewInt(123)}, - pulsar: &pulsar_testpb.IntAsBytes{IntAsBytes: int123bz}, + gogo: &gogo_testpb.IntAsBytes{IntAsBytes: math.NewInt(123)}, }, "math/int_as_bytes/empty": { - gogo: &gogo_testpb.IntAsBytes{}, - pulsar: &pulsar_testpb.IntAsBytes{}, + gogo: &gogo_testpb.IntAsBytes{}, }, } for name, tc := range cases { t.Run(name, func(t *testing.T) { - gogoBytes, err := encCfg.Amino.MarshalJSON(tc.gogo) - require.NoError(t, err) - - pulsarBytes, err := aj.Marshal(tc.pulsar) - if tc.pulsarMarshalFails { - require.Error(t, err) - return - } - require.NoError(t, err) - - fmt.Printf("pulsar: %s\n", string(pulsarBytes)) - fmt.Printf(" gogo: %s\n", string(gogoBytes)) - require.Equal(t, string(gogoBytes), string(pulsarBytes)) - - pulsarProtoBytes, err := proto.Marshal(tc.pulsar) - require.NoError(t, err) - - gogoType := reflect.TypeOf(tc.gogo).Elem() - newGogo := reflect.New(gogoType).Interface().(gogoproto.Message) - - err = encCfg.Codec.Unmarshal(pulsarProtoBytes, newGogo) - if tc.protoUnmarshalFails { - require.Error(t, err) - return - } + legacyBytes := fixture.MarshalLegacyAminoJSON(t, tc.gogo) + dynamicBytes, err := aj.Marshal(fixture.DynamicMessage(t, tc.gogo)) require.NoError(t, err) - newGogoBytes, err := encCfg.Amino.MarshalJSON(newGogo) - require.NoError(t, err) - if tc.roundTripUnequal { - require.NotEqual(t, string(gogoBytes), string(newGogoBytes)) + t.Logf("legacy: %s\n", string(legacyBytes)) + t.Logf(" sut: %s\n", string(dynamicBytes)) + if tc.fails { + require.NotEqual(t, string(legacyBytes), string(dynamicBytes)) return } - require.Equal(t, string(gogoBytes), string(newGogoBytes)) + require.Equal(t, string(legacyBytes), string(dynamicBytes)) // test amino json signer handler equivalence - msg, ok := tc.gogo.(legacytx.LegacyMsg) - if !ok { + if !proto.HasExtension(fixture.MessageDescriptor(t, tc.gogo).Options(), msgv1.E_Signer) { // not signable return } - - handlerOptions := signing_testutil.HandlerArgumentOptions{ - ChainID: "test-chain", - Memo: "sometestmemo", - Msg: tc.pulsar, - AccNum: 1, - AccSeq: 2, - SignerAddress: "signerAddress", - Fee: &txv1beta1.Fee{ - Amount: []*v1beta1.Coin{{Denom: "uatom", Amount: "1000"}}, - }, - } - - signerData, txData, err := signing_testutil.MakeHandlerArguments(handlerOptions) - require.NoError(t, err) - - handler := aminojson.NewSignModeHandler(aminojson.SignModeHandlerOptions{}) - signBz, err := handler.GetSignBytes(context.Background(), signerData, txData) - require.NoError(t, err) - - legacyHandler := tx.NewSignModeLegacyAminoJSONHandler() - txBuilder := encCfg.TxConfig.NewTxBuilder() - require.NoError(t, txBuilder.SetMsgs([]types.Msg{msg}...)) - txBuilder.SetMemo(handlerOptions.Memo) - txBuilder.SetFeeAmount(types.Coins{types.NewInt64Coin("uatom", 1000)}) - theTx := txBuilder.GetTx() - - legacySigningData := signing.SignerData{ - ChainID: handlerOptions.ChainID, - Address: handlerOptions.SignerAddress, - AccountNumber: handlerOptions.AccNum, - Sequence: handlerOptions.AccSeq, - } - legacySignBz, err := legacyHandler.GetSignBytes(signingtypes.SignMode_SIGN_MODE_LEGACY_AMINO_JSON, - legacySigningData, theTx) - require.NoError(t, err) - require.Equal(t, string(legacySignBz), string(signBz)) + fixture.RequireLegacyAminoEquivalent(t, tc.gogo) }) } } func TestSendAuthorization(t *testing.T) { - encCfg := testutil.MakeTestEncodingConfig(codectestutil.CodecOptions{}, auth.AppModule{}, authzmodule.AppModule{}, - distribution.AppModule{}, bank.AppModule{}) + encCfg := testutil.MakeTestEncodingConfig( + codectestutil.CodecOptions{}, + auth.AppModule{}, + authzmodule.AppModule{}, + distribution.AppModule{}, + bank.AppModule{}, + ) aj := aminojson.NewEncoder(aminojson.EncoderOptions{}) diff --git a/tests/integration/tx/context_test.go b/tests/integration/tx/context_test.go index ffe21c2053cb..eb6ce3250160 100644 --- a/tests/integration/tx/context_test.go +++ b/tests/integration/tx/context_test.go @@ -4,7 +4,6 @@ import ( "testing" "github.com/stretchr/testify/require" - "google.golang.org/protobuf/proto" "cosmossdk.io/depinject" "cosmossdk.io/log" @@ -12,21 +11,14 @@ import ( "cosmossdk.io/x/tx/signing" codectypes "github.com/cosmos/cosmos-sdk/codec/types" + "github.com/cosmos/cosmos-sdk/tests/integration/tx/internal" "github.com/cosmos/cosmos-sdk/tests/integration/tx/internal/pulsar/testpb" "github.com/cosmos/cosmos-sdk/testutil/configurator" simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" ) -func ProvideCustomGetSigners() signing.CustomGetSigner { - return signing.CustomGetSigner{ - MsgType: proto.MessageName(&testpb.TestRepeatedFields{}), - Fn: func(msg proto.Message) ([][]byte, error) { - testMsg := msg.(*testpb.TestRepeatedFields) - // arbitrary logic - signer := testMsg.NullableDontOmitempty[1].Value - return [][]byte{[]byte(signer)}, nil - }, - } +func ProvideCustomGetSigner() signing.CustomGetSigner { + return internal.TestRepeatedFieldsSigner } func TestDefineCustomGetSigners(t *testing.T) { @@ -41,7 +33,7 @@ func TestDefineCustomGetSigners(t *testing.T) { configurator.ConsensusModule(), ), depinject.Supply(log.NewNopLogger()), - depinject.Provide(ProvideCustomGetSigners), + depinject.Provide(ProvideCustomGetSigner), ), &interfaceRegistry, ) diff --git a/tests/integration/tx/internal/util.go b/tests/integration/tx/internal/util.go new file mode 100644 index 000000000000..d2e654a58816 --- /dev/null +++ b/tests/integration/tx/internal/util.go @@ -0,0 +1,221 @@ +package internal + +import ( + "bytes" + "context" + "encoding/json" + "testing" + + gogoproto "github.com/cosmos/gogoproto/proto" + "github.com/stretchr/testify/require" + "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/reflect/protoreflect" + "google.golang.org/protobuf/types/dynamicpb" + + "cosmossdk.io/core/transaction" + "cosmossdk.io/x/tx/signing" + "cosmossdk.io/x/tx/signing/aminojson" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/codec" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + "github.com/cosmos/cosmos-sdk/std" + "github.com/cosmos/cosmos-sdk/tests/integration/tx/internal/pulsar/testpb" + "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/module" + signingtypes "github.com/cosmos/cosmos-sdk/types/tx/signing" + "github.com/cosmos/cosmos-sdk/x/auth/migrations/legacytx" + authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing" + "github.com/cosmos/cosmos-sdk/x/auth/tx" +) + +var TestRepeatedFieldsSigner = signing.CustomGetSigner{ + MsgType: proto.MessageName(&testpb.TestRepeatedFields{}), + Fn: func(msg proto.Message) ([][]byte, error) { + testMsg := msg.(*testpb.TestRepeatedFields) + // arbitrary logic + signer := testMsg.NullableDontOmitempty[1].Value + return [][]byte{[]byte(signer)}, nil + }, +} + +type noOpAddressCodec struct{} + +func (a noOpAddressCodec) StringToBytes(text string) ([]byte, error) { + return []byte(text), nil +} + +func (a noOpAddressCodec) BytesToString(bz []byte) (string, error) { + return string(bz), nil +} + +type SigningFixture struct { + txConfig client.TxConfig + legacy *codec.LegacyAmino + protoCodec *codec.ProtoCodec + options SigningFixtureOptions + registry codectypes.InterfaceRegistry +} + +type SigningFixtureOptions struct { + DoNotSortFields bool +} + +func NewSigningFixture( + t *testing.T, + options SigningFixtureOptions, + modules ...module.AppModule, +) *SigningFixture { + t.Helper() + // set up transaction and signing infra + addressCodec, valAddressCodec := noOpAddressCodec{}, noOpAddressCodec{} + customGetSigners := []signing.CustomGetSigner{TestRepeatedFieldsSigner} + interfaceRegistry, _, err := codec.ProvideInterfaceRegistry( + addressCodec, + valAddressCodec, + customGetSigners, + ) + require.NoError(t, err) + protoCodec := codec.ProvideProtoCodec(interfaceRegistry) + signingOptions := &signing.Options{ + FileResolver: interfaceRegistry, + AddressCodec: addressCodec, + ValidatorAddressCodec: valAddressCodec, + } + for _, customGetSigner := range customGetSigners { + signingOptions.DefineCustomGetSigners(customGetSigner.MsgType, customGetSigner.Fn) + } + txConfig, err := tx.NewTxConfigWithOptions( + protoCodec, + tx.ConfigOptions{ + EnabledSignModes: []signingtypes.SignMode{ + signingtypes.SignMode_SIGN_MODE_LEGACY_AMINO_JSON, + }, + SigningOptions: signingOptions, + }) + require.NoError(t, err) + + legacyAminoCodec := codec.NewLegacyAmino() + mb := module.NewManager(modules...) + std.RegisterLegacyAminoCodec(legacyAminoCodec) + std.RegisterInterfaces(interfaceRegistry) + mb.RegisterLegacyAminoCodec(legacyAminoCodec) + mb.RegisterInterfaces(interfaceRegistry) + + return &SigningFixture{ + txConfig: txConfig, + legacy: legacyAminoCodec, + options: options, + protoCodec: protoCodec, + registry: interfaceRegistry, + } +} + +func (s *SigningFixture) RequireLegacyAminoEquivalent(t *testing.T, msg transaction.Msg) { + t.Helper() + // create tx envelope + txBuilder := s.txConfig.NewTxBuilder() + err := txBuilder.SetMsgs([]types.Msg{msg}...) + require.NoError(t, err) + builtTx := txBuilder.GetTx() + + // round trip it to simulate application usage + txBz, err := s.txConfig.TxEncoder()(builtTx) + require.NoError(t, err) + theTx, err := s.txConfig.TxDecoder()(txBz) + require.NoError(t, err) + + // create signing envelope + signerData := signing.SignerData{ + Address: "sender-address", + ChainID: "test-chain", + AccountNumber: 0, + Sequence: 0, + } + adaptableTx, ok := theTx.(authsigning.V2AdaptableTx) + require.True(t, ok) + + legacytx.RegressionTestingAminoCodec = s.legacy + defer func() { + legacytx.RegressionTestingAminoCodec = nil + }() + legacyAminoSignHandler := tx.NewSignModeLegacyAminoJSONHandler() + legacyBz, err := legacyAminoSignHandler.GetSignBytes( + signingtypes.SignMode_SIGN_MODE_LEGACY_AMINO_JSON, + authsigning.SignerData{ + ChainID: signerData.ChainID, + Address: signerData.Address, + AccountNumber: signerData.AccountNumber, + Sequence: signerData.Sequence, + }, + theTx) + require.NoError(t, err) + + handler := aminojson.NewSignModeHandler(aminojson.SignModeHandlerOptions{}) + signBz, err := handler.GetSignBytes( + context.Background(), + signerData, + adaptableTx.GetSigningTxData(), + ) + require.NoError(t, err) + + require.Truef(t, + bytes.Equal(legacyBz, signBz), + "legacy: %s\n x/tx: %s", string(legacyBz), string(signBz)) +} + +func (s *SigningFixture) MarshalLegacyAminoJSON(t *testing.T, o any) []byte { + t.Helper() + bz, err := s.legacy.MarshalJSON(o) + require.NoError(t, err) + if s.options.DoNotSortFields { + return bz + } + sortedBz, err := sortJson(bz) + require.NoError(t, err) + return sortedBz +} + +func (s *SigningFixture) UnmarshalGogoProto(bz []byte, ptr transaction.Msg) error { + return s.protoCodec.Unmarshal(bz, ptr) +} + +func (s *SigningFixture) MessageDescriptor(t *testing.T, msg transaction.Msg) protoreflect.MessageDescriptor { + t.Helper() + typeName := gogoproto.MessageName(msg) + msgDesc, err := s.registry.FindDescriptorByName(protoreflect.FullName(typeName)) + require.NoError(t, err) + return msgDesc.(protoreflect.MessageDescriptor) +} + +// DynamicMessage is identical to the Decoder implementation in +// https://github.com/cosmos/cosmos-sdk/blob/6d2f6ff068c81c5783e01319beaa51c7dbb43edd/x/tx/decode/decode.go#L136 +// It is duplicated here to test dynamic message implementations specifically. +// The code path linked above is also covered in this package. +func (s *SigningFixture) DynamicMessage(t *testing.T, msg transaction.Msg) proto.Message { + t.Helper() + msgDesc := s.MessageDescriptor(t, msg) + protoBz, err := gogoproto.Marshal(msg) + require.NoError(t, err) + dynamicMsg := dynamicpb.NewMessageType(msgDesc).New().Interface() + err = proto.Unmarshal(protoBz, dynamicMsg) + require.NoError(t, err) + return dynamicMsg +} + +// sortJson sorts the JSON bytes by way of the side effect of unmarshalling and remarshalling +// the JSON using encoding/json. This hacky way of sorting JSON fields was used by the legacy +// amino JSON encoding x/auth/migrations/legacytx.StdSignBytes. It is used here ensure the x/tx +// JSON encoding is equivalent to the legacy amino JSON encoding. +func sortJson(bz []byte) ([]byte, error) { + var c any + err := json.Unmarshal(bz, &c) + if err != nil { + return nil, err + } + js, err := json.Marshal(c) + if err != nil { + return nil, err + } + return js, nil +} diff --git a/tests/sims/authz/operations_test.go b/tests/sims/authz/operations_test.go deleted file mode 100644 index 3769d30c798b..000000000000 --- a/tests/sims/authz/operations_test.go +++ /dev/null @@ -1,224 +0,0 @@ -package authz - -import ( - "math/rand" - "testing" - "time" - - "github.com/cosmos/gogoproto/proto" - "github.com/stretchr/testify/suite" - - "cosmossdk.io/core/header" - coretesting "cosmossdk.io/core/testing" - "cosmossdk.io/depinject" - _ "cosmossdk.io/x/accounts" // import as blank for app wiring - "cosmossdk.io/x/authz" - authzkeeper "cosmossdk.io/x/authz/keeper" - _ "cosmossdk.io/x/authz/module" // import as blank for app wiring - "cosmossdk.io/x/authz/simulation" - _ "cosmossdk.io/x/bank" // import as blank for app wiring - bankkeeper "cosmossdk.io/x/bank/keeper" - banktestutil "cosmossdk.io/x/bank/testutil" - banktypes "cosmossdk.io/x/bank/types" - _ "cosmossdk.io/x/consensus" // import as blank for app wiring - _ "cosmossdk.io/x/gov" // import as blank for app wiring - _ "cosmossdk.io/x/mint" // import as blank for app wiring - _ "cosmossdk.io/x/staking" // import as blank for app wiring - - "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/codec" - codectypes "github.com/cosmos/cosmos-sdk/codec/types" - "github.com/cosmos/cosmos-sdk/runtime" - "github.com/cosmos/cosmos-sdk/testutil/configurator" - simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" - sdk "github.com/cosmos/cosmos-sdk/types" - simtypes "github.com/cosmos/cosmos-sdk/types/simulation" - _ "github.com/cosmos/cosmos-sdk/x/auth" // import as blank for app wiring - authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper" - _ "github.com/cosmos/cosmos-sdk/x/auth/tx/config" // import as blank for app wiring - _ "github.com/cosmos/cosmos-sdk/x/genutil" // import as blank for app wiring -) - -var AppConfig = configurator.NewAppConfig( - configurator.AccountsModule(), - configurator.AuthModule(), - configurator.BankModule(), - configurator.StakingModule(), - configurator.TxModule(), - configurator.ConsensusModule(), - configurator.GenutilModule(), - configurator.AuthzModule(), - configurator.MintModule(), -) - -type SimTestSuite struct { - suite.Suite - - ctx sdk.Context - - app *runtime.App - codec codec.Codec - interfaceRegistry codectypes.InterfaceRegistry - txConfig client.TxConfig - accountKeeper authkeeper.AccountKeeper - bankKeeper bankkeeper.Keeper - authzKeeper authzkeeper.Keeper -} - -func (suite *SimTestSuite) SetupTest() { - app, err := simtestutil.Setup( - depinject.Configs( - AppConfig, - depinject.Supply(coretesting.NewNopLogger()), - ), - &suite.codec, - &suite.interfaceRegistry, - &suite.txConfig, - &suite.accountKeeper, - &suite.bankKeeper, - &suite.authzKeeper, - ) - suite.Require().NoError(err) - suite.app = app - suite.ctx = app.BaseApp.NewContext(false) -} - -func (suite *SimTestSuite) TestWeightedOperations() { - cdc := suite.codec - appParams := make(simtypes.AppParams) - - weightedOps := simulation.WeightedOperations(suite.interfaceRegistry, appParams, cdc, suite.txConfig, suite.accountKeeper, - suite.bankKeeper, suite.authzKeeper) - - s := rand.NewSource(3) - r := rand.New(s) - // setup 2 accounts - accs := suite.getTestingAccounts(r, 2) - - expected := []struct { - weight int - opMsgRoute string - opMsgName string - }{ - {simulation.WeightGrant, authz.ModuleName, simulation.TypeMsgGrant}, - {simulation.WeightExec, authz.ModuleName, simulation.TypeMsgExec}, - {simulation.WeightRevoke, authz.ModuleName, simulation.TypeMsgRevoke}, - } - - require := suite.Require() - for i, w := range weightedOps { - op, _, err := w.Op()(r, suite.app.BaseApp, suite.ctx, accs, "") - require.NoError(err) - - // the following checks are very much dependent from the ordering of the output given - // by WeightedOperations. if the ordering in WeightedOperations changes some tests - // will fail - require.Equal(expected[i].weight, w.Weight(), "weight should be the same. %v", op.Comment) - require.Equal(expected[i].opMsgRoute, op.Route, "route should be the same. %v", op.Comment) - require.Equal(expected[i].opMsgName, op.Name, "operation Msg name should be the same %v", op.Comment) - } -} - -func (suite *SimTestSuite) getTestingAccounts(r *rand.Rand, n int) []simtypes.Account { - accounts := simtypes.RandomAccounts(r, n) - - initAmt := sdk.TokensFromConsensusPower(200000, sdk.DefaultPowerReduction) - initCoins := sdk.NewCoins(sdk.NewCoin("stake", initAmt)) - - // add coins to the accounts - for _, account := range accounts { - acc := suite.accountKeeper.NewAccountWithAddress(suite.ctx, account.Address) - suite.accountKeeper.SetAccount(suite.ctx, acc) - suite.Require().NoError(banktestutil.FundAccount(suite.ctx, suite.bankKeeper, account.Address, initCoins)) - } - - return accounts -} - -func (suite *SimTestSuite) TestSimulateGrant() { - s := rand.NewSource(1) - r := rand.New(s) - accounts := suite.getTestingAccounts(r, 2) - blockTime := time.Now().UTC() - ctx := suite.ctx.WithHeaderInfo(header.Info{Time: blockTime}) - - granter := accounts[0] - grantee := accounts[1] - - // execute operation - op := simulation.SimulateMsgGrant(codec.NewProtoCodec(suite.interfaceRegistry), suite.txConfig, suite.accountKeeper, suite.bankKeeper, suite.authzKeeper) - operationMsg, futureOperations, err := op(r, suite.app.BaseApp, ctx, accounts, "") - suite.Require().NoError(err) - - var msg authz.MsgGrant - err = proto.Unmarshal(operationMsg.Msg, &msg) - suite.Require().NoError(err) - suite.Require().True(operationMsg.OK) - suite.Require().Equal(granter.Address.String(), msg.Granter) - suite.Require().Equal(grantee.Address.String(), msg.Grantee) - suite.Require().Len(futureOperations, 0) -} - -func (suite *SimTestSuite) TestSimulateRevoke() { - // setup 3 accounts - s := rand.NewSource(2) - r := rand.New(s) - accounts := suite.getTestingAccounts(r, 3) - initAmt := sdk.TokensFromConsensusPower(200000, sdk.DefaultPowerReduction) - initCoins := sdk.NewCoins(sdk.NewCoin("stake", initAmt)) - - granter := accounts[0] - grantee := accounts[1] - a := banktypes.NewSendAuthorization(initCoins, nil, suite.accountKeeper.AddressCodec()) - expire := time.Now().Add(30 * time.Hour) - - err := suite.authzKeeper.SaveGrant(suite.ctx, grantee.Address, granter.Address, a, &expire) - suite.Require().NoError(err) - - // execute operation - op := simulation.SimulateMsgRevoke(codec.NewProtoCodec(suite.interfaceRegistry), suite.txConfig, suite.accountKeeper, suite.bankKeeper, suite.authzKeeper) - operationMsg, futureOperations, err := op(r, suite.app.BaseApp, suite.ctx, accounts, "") - suite.Require().NoError(err) - - var msg authz.MsgRevoke - err = proto.Unmarshal(operationMsg.Msg, &msg) - suite.Require().NoError(err) - suite.Require().True(operationMsg.OK) - suite.Require().Equal(granter.Address.String(), msg.Granter) - suite.Require().Equal(grantee.Address.String(), msg.Grantee) - suite.Require().Equal(banktypes.SendAuthorization{}.MsgTypeURL(), msg.MsgTypeUrl) - suite.Require().Len(futureOperations, 0) -} - -func (suite *SimTestSuite) TestSimulateExec() { - // setup 3 accounts - s := rand.NewSource(1) - r := rand.New(s) - accounts := suite.getTestingAccounts(r, 3) - initAmt := sdk.TokensFromConsensusPower(200000, sdk.DefaultPowerReduction) - initCoins := sdk.NewCoins(sdk.NewCoin("stake", initAmt)) - - granter := accounts[0] - grantee := accounts[1] - a := banktypes.NewSendAuthorization(initCoins, nil, suite.accountKeeper.AddressCodec()) - expire := suite.ctx.HeaderInfo().Time.Add(1 * time.Hour) - - err := suite.authzKeeper.SaveGrant(suite.ctx, grantee.Address, granter.Address, a, &expire) - suite.Require().NoError(err) - - // execute operation - op := simulation.SimulateMsgExec(codec.NewProtoCodec(suite.interfaceRegistry), suite.txConfig, suite.accountKeeper, suite.bankKeeper, suite.authzKeeper, suite.codec) - operationMsg, futureOperations, err := op(r, suite.app.BaseApp, suite.ctx, accounts, "") - suite.Require().NoError(err) - - var msg authz.MsgExec - err = proto.Unmarshal(operationMsg.Msg, &msg) - suite.Require().NoError(err) - suite.Require().True(operationMsg.OK) - suite.Require().Equal(grantee.Address.String(), msg.Grantee) - suite.Require().Len(futureOperations, 0) -} - -func TestSimTestSuite(t *testing.T) { - suite.Run(t, new(SimTestSuite)) -} diff --git a/tests/sims/bank/operations_test.go b/tests/sims/bank/operations_test.go deleted file mode 100644 index e2177fb14a20..000000000000 --- a/tests/sims/bank/operations_test.go +++ /dev/null @@ -1,217 +0,0 @@ -package simulation_test - -import ( - "math/rand" - "testing" - - "github.com/cosmos/gogoproto/proto" - "github.com/stretchr/testify/suite" - - "cosmossdk.io/depinject" - "cosmossdk.io/log" - _ "cosmossdk.io/x/accounts" - _ "cosmossdk.io/x/bank" - "cosmossdk.io/x/bank/keeper" - "cosmossdk.io/x/bank/simulation" - "cosmossdk.io/x/bank/testutil" - "cosmossdk.io/x/bank/types" - _ "cosmossdk.io/x/consensus" - _ "cosmossdk.io/x/staking" - - "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/codec" - "github.com/cosmos/cosmos-sdk/runtime" - "github.com/cosmos/cosmos-sdk/testutil/configurator" - simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" - sdk "github.com/cosmos/cosmos-sdk/types" - simtypes "github.com/cosmos/cosmos-sdk/types/simulation" - _ "github.com/cosmos/cosmos-sdk/x/auth" - _ "github.com/cosmos/cosmos-sdk/x/auth/tx/config" -) - -type SimTestSuite struct { - suite.Suite - - ctx sdk.Context - accountKeeper types.AccountKeeper - bankKeeper keeper.Keeper - cdc codec.Codec - txConfig client.TxConfig - app *runtime.App -} - -func (suite *SimTestSuite) SetupTest() { - var ( - appBuilder *runtime.AppBuilder - err error - ) - suite.app, err = simtestutil.Setup( - depinject.Configs( - configurator.NewAppConfig( - configurator.AccountsModule(), - configurator.AuthModule(), - configurator.BankModule(), - configurator.StakingModule(), - configurator.ConsensusModule(), - configurator.TxModule(), - ), - depinject.Supply(log.NewNopLogger()), - ), &suite.accountKeeper, &suite.bankKeeper, &suite.cdc, &suite.txConfig, &appBuilder) - - suite.NoError(err) - - suite.ctx = suite.app.BaseApp.NewContext(false) -} - -// TestWeightedOperations tests the weights of the operations. -func (suite *SimTestSuite) TestWeightedOperations() { - cdc := suite.cdc - appParams := make(simtypes.AppParams) - - weightesOps := simulation.WeightedOperations(appParams, cdc, suite.txConfig, suite.accountKeeper, suite.bankKeeper) - - // setup 3 accounts - s := rand.NewSource(1) - r := rand.New(s) - accs := suite.getTestingAccounts(r, 3) - - expected := []struct { - weight int - opMsgRoute string - opMsgName string - }{ - {100, types.ModuleName, sdk.MsgTypeURL(&types.MsgSend{})}, - {10, types.ModuleName, sdk.MsgTypeURL(&types.MsgMultiSend{})}, - } - - for i, w := range weightesOps { - operationMsg, _, err := w.Op()(r, suite.app.BaseApp, suite.ctx, accs, "") - suite.Require().NoError(err) - - // the following checks are very much dependent from the ordering of the output given - // by WeightedOperations. if the ordering in WeightedOperations changes some tests - // will fail - suite.Require().Equal(expected[i].weight, w.Weight(), "weight should be the same") - suite.Require().Equal(expected[i].opMsgRoute, operationMsg.Route, "route should be the same") - suite.Require().Equal(expected[i].opMsgName, operationMsg.Name, "operation Msg name should be the same") - } -} - -// TestSimulateMsgSend tests the normal scenario of a valid message of type TypeMsgSend. -// Abonormal scenarios, where the message is created by an errors, are not tested here. -func (suite *SimTestSuite) TestSimulateMsgSend() { - // setup 3 accounts - s := rand.NewSource(1) - r := rand.New(s) - accounts := suite.getTestingAccounts(r, 3) - - // execute operation - op := simulation.SimulateMsgSend(suite.txConfig, suite.accountKeeper, suite.bankKeeper) - operationMsg, futureOperations, err := op(r, suite.app.BaseApp, suite.ctx, accounts, "") - suite.Require().NoError(err) - - var msg types.MsgSend - err = proto.Unmarshal(operationMsg.Msg, &msg) - suite.Require().NoError(err) - suite.Require().True(operationMsg.OK) - suite.Require().Equal("65337742stake", msg.Amount.String()) - suite.Require().Equal("cosmos1ghekyjucln7y67ntx7cf27m9dpuxxemn4c8g4r", msg.FromAddress) - suite.Require().Equal("cosmos1p8wcgrjr4pjju90xg6u9cgq55dxwq8j7u4x9a0", msg.ToAddress) - suite.Require().Equal(sdk.MsgTypeURL(&types.MsgSend{}), sdk.MsgTypeURL(&msg)) - suite.Require().Len(futureOperations, 0) -} - -// TestSimulateMsgMultiSend tests the normal scenario of a valid message of type TypeMsgMultiSend. -// Abonormal scenarios, where the message is created by an errors, are not tested here. -func (suite *SimTestSuite) TestSimulateMsgMultiSend() { - // setup 3 accounts - s := rand.NewSource(1) - r := rand.New(s) - accounts := suite.getTestingAccounts(r, 3) - - // execute operation - op := simulation.SimulateMsgMultiSend(suite.txConfig, suite.accountKeeper, suite.bankKeeper) - operationMsg, futureOperations, err := op(r, suite.app.BaseApp, suite.ctx, accounts, "") - require := suite.Require() - require.NoError(err) - - var msg types.MsgMultiSend - err = proto.Unmarshal(operationMsg.Msg, &msg) - suite.Require().NoError(err) - require.True(operationMsg.OK) - require.Len(msg.Inputs, 1) - require.Equal("cosmos1tnh2q55v8wyygtt9srz5safamzdengsnqeycj3", msg.Inputs[0].Address) - require.Equal("114949958stake", msg.Inputs[0].Coins.String()) - require.Len(msg.Outputs, 2) - require.Equal("cosmos1ghekyjucln7y67ntx7cf27m9dpuxxemn4c8g4r", msg.Outputs[1].Address) - require.Equal("107287087stake", msg.Outputs[1].Coins.String()) - suite.Require().Equal(sdk.MsgTypeURL(&types.MsgMultiSend{}), sdk.MsgTypeURL(&msg)) - require.Len(futureOperations, 0) -} - -func (suite *SimTestSuite) TestSimulateModuleAccountMsgSend() { - const moduleAccount = 1 - - s := rand.NewSource(1) - r := rand.New(s) - accounts := suite.getTestingAccounts(r, 1) - - // execute operation - op := simulation.SimulateMsgSendToModuleAccount(suite.txConfig, suite.accountKeeper, suite.bankKeeper, moduleAccount) - - s = rand.NewSource(1) - r = rand.New(s) - - operationMsg, futureOperations, err := op(r, suite.app.BaseApp, suite.ctx, accounts, "") - suite.Require().Error(err) - - var msg types.MsgSend - err = proto.Unmarshal(operationMsg.Msg, &msg) - suite.Require().NoError(err) - suite.Require().False(operationMsg.OK) - suite.Require().Equal(operationMsg.Comment, "invalid transfers") - suite.Require().Equal(sdk.MsgTypeURL(&types.MsgSend{}), sdk.MsgTypeURL(&msg)) - suite.Require().Len(futureOperations, 0) -} - -func (suite *SimTestSuite) TestSimulateMsgMultiSendToModuleAccount() { - const mAccount = 2 - - s := rand.NewSource(1) - r := rand.New(s) - accounts := suite.getTestingAccounts(r, 2) - - // execute operation - op := simulation.SimulateMsgMultiSendToModuleAccount(suite.txConfig, suite.accountKeeper, suite.bankKeeper, mAccount) - - operationMsg, futureOperations, err := op(r, suite.app.BaseApp, suite.ctx, accounts, "") - suite.Require().Error(err) - - var msg types.MsgMultiSend - err = proto.Unmarshal(operationMsg.Msg, &msg) - suite.Require().NoError(err) - suite.Require().False(operationMsg.OK) // sending tokens to a module account should fail - suite.Require().Equal(operationMsg.Comment, "invalid transfers") - suite.Require().Equal(sdk.MsgTypeURL(&types.MsgMultiSend{}), sdk.MsgTypeURL(&msg)) - suite.Require().Len(futureOperations, 0) -} - -func (suite *SimTestSuite) getTestingAccounts(r *rand.Rand, n int) []simtypes.Account { - accounts := simtypes.RandomAccounts(r, n) - - initAmt := sdk.TokensFromConsensusPower(200, sdk.DefaultPowerReduction) - initCoins := sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, initAmt)) - - // add coins to the accounts - for _, account := range accounts { - acc := suite.accountKeeper.NewAccountWithAddress(suite.ctx, account.Address) - suite.accountKeeper.SetAccount(suite.ctx, acc) - suite.Require().NoError(testutil.FundAccount(suite.ctx, suite.bankKeeper, account.Address, initCoins)) - } - - return accounts -} - -func TestSimTestSuite(t *testing.T) { - suite.Run(t, new(SimTestSuite)) -} diff --git a/tests/sims/distribution/app_config.go b/tests/sims/distribution/app_config.go deleted file mode 100644 index 989d74b74f5a..000000000000 --- a/tests/sims/distribution/app_config.go +++ /dev/null @@ -1,29 +0,0 @@ -package distribution - -import ( - _ "cosmossdk.io/x/accounts" // import as blank for app wiring - _ "cosmossdk.io/x/bank" // import as blank for app wiring - _ "cosmossdk.io/x/consensus" // import as blank for app wiring - _ "cosmossdk.io/x/distribution" // import as blank for app wiring - _ "cosmossdk.io/x/mint" // import as blank for app wiring - _ "cosmossdk.io/x/protocolpool" // import as blank for app wiring - _ "cosmossdk.io/x/staking" // import as blank for app wiring - - "github.com/cosmos/cosmos-sdk/testutil/configurator" - _ "github.com/cosmos/cosmos-sdk/x/auth" // import as blank for app wiring - _ "github.com/cosmos/cosmos-sdk/x/auth/tx/config" // import as blank for app wiring - _ "github.com/cosmos/cosmos-sdk/x/genutil" // import as blank for app wiring -) - -var AppConfig = configurator.NewAppConfig( - configurator.AccountsModule(), - configurator.AuthModule(), - configurator.BankModule(), - configurator.StakingModule(), - configurator.TxModule(), - configurator.ConsensusModule(), - configurator.GenutilModule(), - configurator.DistributionModule(), - configurator.MintModule(), - configurator.ProtocolPoolModule(), -) diff --git a/tests/sims/distribution/operations_test.go b/tests/sims/distribution/operations_test.go deleted file mode 100644 index 972217c6cf37..000000000000 --- a/tests/sims/distribution/operations_test.go +++ /dev/null @@ -1,287 +0,0 @@ -package distribution - -import ( - "math/rand" - "testing" - - "github.com/cosmos/gogoproto/proto" - "github.com/stretchr/testify/suite" - - "cosmossdk.io/collections" - "cosmossdk.io/depinject" - "cosmossdk.io/log" - "cosmossdk.io/math" - bankkeeper "cosmossdk.io/x/bank/keeper" - banktestutil "cosmossdk.io/x/bank/testutil" - "cosmossdk.io/x/distribution/keeper" - "cosmossdk.io/x/distribution/simulation" - "cosmossdk.io/x/distribution/types" - stakingkeeper "cosmossdk.io/x/staking/keeper" - stakingtypes "cosmossdk.io/x/staking/types" - - "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/codec" - "github.com/cosmos/cosmos-sdk/codec/address" - "github.com/cosmos/cosmos-sdk/runtime" - simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" - sdk "github.com/cosmos/cosmos-sdk/types" - simtypes "github.com/cosmos/cosmos-sdk/types/simulation" - authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper" -) - -// TestWeightedOperations tests the weights of the operations. -func (suite *SimTestSuite) TestWeightedOperations() { - appParams := make(simtypes.AppParams) - - weightedOps := simulation.WeightedOperations(appParams, suite.cdc, suite.txConfig, suite.accountKeeper, - suite.bankKeeper, suite.distrKeeper, suite.stakingKeeper) - - // setup 3 accounts - s := rand.NewSource(1) - r := rand.New(s) - accs := suite.getTestingAccounts(r, 3) - - expected := []struct { - weight int - opMsgRoute string - opMsgName string - }{ - {simulation.DefaultWeightMsgSetWithdrawAddress, types.ModuleName, sdk.MsgTypeURL(&types.MsgSetWithdrawAddress{})}, - {simulation.DefaultWeightMsgWithdrawDelegationReward, types.ModuleName, sdk.MsgTypeURL(&types.MsgWithdrawDelegatorReward{})}, - {simulation.DefaultWeightMsgWithdrawValidatorCommission, types.ModuleName, sdk.MsgTypeURL(&types.MsgWithdrawValidatorCommission{})}, - } - - for i, w := range weightedOps { - operationMsg, _, err := w.Op()(r, suite.app.BaseApp, suite.ctx, accs, "") - suite.Require().NoError(err) - - // the following checks are very much dependent from the ordering of the output given - // by WeightedOperations. if the ordering in WeightedOperations changes some tests - // will fail - suite.Require().Equal(expected[i].weight, w.Weight(), "weight should be the same") - suite.Require().Equal(expected[i].opMsgRoute, operationMsg.Route, "route should be the same") - suite.Require().Equal(expected[i].opMsgName, operationMsg.Name, "operation Msg name should be the same") - } -} - -// TestSimulateMsgSetWithdrawAddress tests the normal scenario of a valid message of type TypeMsgSetWithdrawAddress. -// Abonormal scenarios, where the message is created by an errors, are not tested here. -func (suite *SimTestSuite) TestSimulateMsgSetWithdrawAddress() { - // setup 3 accounts - s := rand.NewSource(1) - r := rand.New(s) - accounts := suite.getTestingAccounts(r, 3) - - // execute operation - op := simulation.SimulateMsgSetWithdrawAddress(suite.txConfig, suite.accountKeeper, suite.bankKeeper, suite.distrKeeper) - operationMsg, futureOperations, err := op(r, suite.app.BaseApp, suite.ctx, accounts, "") - suite.Require().NoError(err) - - var msg types.MsgSetWithdrawAddress - err = proto.Unmarshal(operationMsg.Msg, &msg) - suite.Require().NoError(err) - suite.Require().True(operationMsg.OK) - suite.Require().Equal("cosmos1ghekyjucln7y67ntx7cf27m9dpuxxemn4c8g4r", msg.DelegatorAddress) - suite.Require().Equal("cosmos1p8wcgrjr4pjju90xg6u9cgq55dxwq8j7u4x9a0", msg.WithdrawAddress) - suite.Require().Equal(sdk.MsgTypeURL(&types.MsgSetWithdrawAddress{}), sdk.MsgTypeURL(&msg)) - suite.Require().Len(futureOperations, 0) -} - -// TestSimulateMsgWithdrawDelegatorReward tests the normal scenario of a valid message -// of type TypeMsgWithdrawDelegatorReward. -// Abonormal scenarios, where the message is created by an errors, are not tested here. -func (suite *SimTestSuite) TestSimulateMsgWithdrawDelegatorReward() { - // setup 3 accounts - s := rand.NewSource(4) - r := rand.New(s) - accounts := suite.getTestingAccounts(r, 3) - - // setup accounts[0] as validator - validator0 := suite.getTestingValidator0(accounts) - - // setup delegation - delTokens := sdk.TokensFromConsensusPower(2, sdk.DefaultPowerReduction) - validator0, issuedShares := validator0.AddTokensFromDel(delTokens) - delegator := accounts[1] - delegation := stakingtypes.NewDelegation(delegator.Address.String(), validator0.GetOperator(), issuedShares) - suite.Require().NoError(suite.stakingKeeper.SetDelegation(suite.ctx, delegation)) - valBz, err := address.NewBech32Codec("cosmosvaloper").StringToBytes(validator0.GetOperator()) - suite.Require().NoError(err) - - suite.Require().NoError(suite.distrKeeper.DelegatorStartingInfo.Set(suite.ctx, collections.Join(sdk.ValAddress(valBz), delegator.Address), types.NewDelegatorStartingInfo(2, math.LegacyOneDec(), 200))) - - suite.setupValidatorRewards(valBz) - - // execute operation - op := simulation.SimulateMsgWithdrawDelegatorReward(suite.txConfig, suite.accountKeeper, suite.bankKeeper, suite.distrKeeper, suite.stakingKeeper) - operationMsg, futureOperations, err := op(r, suite.app.BaseApp, suite.ctx, accounts, "") - suite.Require().NoError(err) - - var msg types.MsgWithdrawDelegatorReward - err = proto.Unmarshal(operationMsg.Msg, &msg) - suite.Require().NoError(err) - suite.Require().True(operationMsg.OK) - suite.Require().Equal("cosmosvaloper1l4s054098kk9hmr5753c6k3m2kw65h686d3mhr", msg.ValidatorAddress) - suite.Require().Equal("cosmos1d6u7zhjwmsucs678d7qn95uqajd4ucl9jcjt26", msg.DelegatorAddress) - suite.Require().Equal(sdk.MsgTypeURL(&types.MsgWithdrawDelegatorReward{}), sdk.MsgTypeURL(&msg)) - suite.Require().Len(futureOperations, 0) -} - -// TestSimulateMsgWithdrawValidatorCommission tests the normal scenario of a valid message -// of type TypeMsgWithdrawValidatorCommission. -// Abonormal scenarios, where the message is created by an errors, are not tested here. -func (suite *SimTestSuite) TestSimulateMsgWithdrawValidatorCommission() { - suite.testSimulateMsgWithdrawValidatorCommission("atoken") - suite.testSimulateMsgWithdrawValidatorCommission("tokenxxx") -} - -// all the checks in this function should not fail if we change the tokenName -func (suite *SimTestSuite) testSimulateMsgWithdrawValidatorCommission(tokenName string) { - // setup 3 accounts - s := rand.NewSource(1) - r := rand.New(s) - accounts := suite.getTestingAccounts(r, 3) - - // setup accounts[0] as validator - validator0 := suite.getTestingValidator0(accounts) - - // set module account coins - distrAcc := suite.distrKeeper.GetDistributionAccount(suite.ctx) - suite.Require().NoError(banktestutil.FundModuleAccount(suite.ctx, suite.bankKeeper, distrAcc.GetName(), sdk.NewCoins( - sdk.NewCoin(tokenName, math.NewInt(10)), - sdk.NewCoin("stake", math.NewInt(5)), - ))) - suite.accountKeeper.SetModuleAccount(suite.ctx, distrAcc) - - // set outstanding rewards - valCommission := sdk.NewDecCoins( - sdk.NewDecCoinFromDec(tokenName, math.LegacyNewDec(5).Quo(math.LegacyNewDec(2))), - sdk.NewDecCoinFromDec("stake", math.LegacyNewDec(1).Quo(math.LegacyNewDec(1))), - ) - valCodec := address.NewBech32Codec("cosmosvaloper") - - val0, err := valCodec.StringToBytes(validator0.GetOperator()) - suite.Require().NoError(err) - - genVal0, err := valCodec.StringToBytes(suite.genesisVals[0].GetOperator()) - suite.Require().NoError(err) - - suite.Require().NoError(suite.distrKeeper.ValidatorOutstandingRewards.Set(suite.ctx, val0, types.ValidatorOutstandingRewards{Rewards: valCommission})) - suite.Require().NoError(suite.distrKeeper.ValidatorOutstandingRewards.Set(suite.ctx, genVal0, types.ValidatorOutstandingRewards{Rewards: valCommission})) - - // setup validator accumulated commission - suite.Require().NoError(suite.distrKeeper.ValidatorsAccumulatedCommission.Set(suite.ctx, val0, types.ValidatorAccumulatedCommission{Commission: valCommission})) - suite.Require().NoError(suite.distrKeeper.ValidatorsAccumulatedCommission.Set(suite.ctx, genVal0, types.ValidatorAccumulatedCommission{Commission: valCommission})) - - // execute operation - op := simulation.SimulateMsgWithdrawValidatorCommission(suite.txConfig, suite.accountKeeper, suite.bankKeeper, suite.distrKeeper, suite.stakingKeeper) - operationMsg, futureOperations, err := op(r, suite.app.BaseApp, suite.ctx, accounts, "") - if !operationMsg.OK { - suite.Require().Equal("could not find account", operationMsg.Comment) - } else { - suite.Require().NoError(err) - - var msg types.MsgWithdrawValidatorCommission - err = proto.Unmarshal(operationMsg.Msg, &msg) - suite.Require().NoError(err) - suite.Require().True(operationMsg.OK) - suite.Require().Equal("cosmosvaloper1tnh2q55v8wyygtt9srz5safamzdengsn9dsd7z", msg.ValidatorAddress) - suite.Require().Equal(sdk.MsgTypeURL(&types.MsgWithdrawValidatorCommission{}), sdk.MsgTypeURL(&msg)) - suite.Require().Len(futureOperations, 0) - } -} - -type SimTestSuite struct { - suite.Suite - - ctx sdk.Context - app *runtime.App - genesisVals []stakingtypes.Validator - - txConfig client.TxConfig - cdc codec.Codec - stakingKeeper *stakingkeeper.Keeper - accountKeeper authkeeper.AccountKeeper - bankKeeper bankkeeper.Keeper - distrKeeper keeper.Keeper -} - -func (suite *SimTestSuite) SetupTest() { - var ( - appBuilder *runtime.AppBuilder - err error - ) - suite.app, err = simtestutil.Setup( - depinject.Configs( - AppConfig, - depinject.Supply(log.NewNopLogger()), - ), - &suite.accountKeeper, - &suite.bankKeeper, - &suite.cdc, - &appBuilder, - &suite.stakingKeeper, - &suite.distrKeeper, - &suite.txConfig, - ) - - suite.NoError(err) - - suite.ctx = suite.app.BaseApp.NewContext(false) - - genesisVals, err := suite.stakingKeeper.GetAllValidators(suite.ctx) - suite.Require().NoError(err) - suite.Require().Len(genesisVals, 1) - suite.genesisVals = genesisVals -} - -func (suite *SimTestSuite) getTestingAccounts(r *rand.Rand, n int) []simtypes.Account { - accounts := simtypes.RandomAccounts(r, n) - - initAmt := suite.stakingKeeper.TokensFromConsensusPower(suite.ctx, 200) - initCoins := sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, initAmt)) - - // add coins to the accounts - for _, account := range accounts { - acc := suite.accountKeeper.NewAccountWithAddress(suite.ctx, account.Address) - suite.accountKeeper.SetAccount(suite.ctx, acc) - suite.Require().NoError(banktestutil.FundAccount(suite.ctx, suite.bankKeeper, account.Address, initCoins)) - } - - return accounts -} - -func (suite *SimTestSuite) getTestingValidator0(accounts []simtypes.Account) stakingtypes.Validator { - commission0 := stakingtypes.NewCommission(math.LegacyZeroDec(), math.LegacyOneDec(), math.LegacyOneDec()) - return suite.getTestingValidator(accounts, commission0, 0) -} - -func (suite *SimTestSuite) getTestingValidator(accounts []simtypes.Account, commission stakingtypes.Commission, n int) stakingtypes.Validator { - require := suite.Require() - account := accounts[n] - valPubKey := account.PubKey - valAddr := sdk.ValAddress(account.PubKey.Address().Bytes()) - validator, err := stakingtypes.NewValidator(valAddr.String(), valPubKey, stakingtypes.Description{}) - require.NoError(err) - validator, err = validator.SetInitialCommission(commission) - require.NoError(err) - validator.DelegatorShares = math.LegacyNewDec(100) - validator.Tokens = math.NewInt(1000000) - - suite.Require().NoError(suite.stakingKeeper.SetValidator(suite.ctx, validator)) - - return validator -} - -func (suite *SimTestSuite) setupValidatorRewards(valAddress sdk.ValAddress) { - decCoins := sdk.DecCoins{sdk.NewDecCoinFromDec(sdk.DefaultBondDenom, math.LegacyOneDec())} - historicalRewards := types.NewValidatorHistoricalRewards(decCoins, 2) - suite.Require().NoError(suite.distrKeeper.ValidatorHistoricalRewards.Set(suite.ctx, collections.Join(valAddress, uint64(2)), historicalRewards)) - // setup current revards - currentRewards := types.NewValidatorCurrentRewards(decCoins, 3) - suite.Require().NoError(suite.distrKeeper.ValidatorCurrentRewards.Set(suite.ctx, valAddress, currentRewards)) -} - -func TestSimTestSuite(t *testing.T) { - suite.Run(t, new(SimTestSuite)) -} diff --git a/tests/sims/feegrant/operations_test.go b/tests/sims/feegrant/operations_test.go deleted file mode 100644 index 11b4f39615c8..000000000000 --- a/tests/sims/feegrant/operations_test.go +++ /dev/null @@ -1,213 +0,0 @@ -package simulation_test - -import ( - "math/rand" - "testing" - "time" - - "github.com/cosmos/gogoproto/proto" - "github.com/stretchr/testify/suite" - - "cosmossdk.io/core/header" - "cosmossdk.io/depinject" - "cosmossdk.io/log" - _ "cosmossdk.io/x/accounts" // import as blank for app wiring - _ "cosmossdk.io/x/bank" - bankkeeper "cosmossdk.io/x/bank/keeper" - banktestutil "cosmossdk.io/x/bank/testutil" - _ "cosmossdk.io/x/consensus" - "cosmossdk.io/x/feegrant" - "cosmossdk.io/x/feegrant/keeper" - _ "cosmossdk.io/x/feegrant/module" - "cosmossdk.io/x/feegrant/simulation" - _ "cosmossdk.io/x/mint" - _ "cosmossdk.io/x/staking" - - "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/codec" - codectypes "github.com/cosmos/cosmos-sdk/codec/types" - "github.com/cosmos/cosmos-sdk/runtime" - "github.com/cosmos/cosmos-sdk/testutil/configurator" - simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" - sdk "github.com/cosmos/cosmos-sdk/types" - simtypes "github.com/cosmos/cosmos-sdk/types/simulation" - _ "github.com/cosmos/cosmos-sdk/x/auth" - authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper" - _ "github.com/cosmos/cosmos-sdk/x/auth/tx/config" - _ "github.com/cosmos/cosmos-sdk/x/genutil" -) - -type SimTestSuite struct { - suite.Suite - - app *runtime.App - ctx sdk.Context - feegrantKeeper keeper.Keeper - interfaceRegistry codectypes.InterfaceRegistry - txConfig client.TxConfig - accountKeeper authkeeper.AccountKeeper - bankKeeper bankkeeper.Keeper - cdc codec.Codec -} - -func (suite *SimTestSuite) SetupTest() { - var err error - suite.app, err = simtestutil.Setup( - depinject.Configs( - configurator.NewAppConfig( - configurator.AccountsModule(), - configurator.AuthModule(), - configurator.BankModule(), - configurator.StakingModule(), - configurator.TxModule(), - configurator.ConsensusModule(), - configurator.GenutilModule(), - configurator.FeegrantModule(), - ), - depinject.Supply(log.NewNopLogger()), - ), - &suite.feegrantKeeper, - &suite.bankKeeper, - &suite.accountKeeper, - &suite.interfaceRegistry, - &suite.txConfig, - &suite.cdc, - ) - suite.Require().NoError(err) - - suite.ctx = suite.app.BaseApp.NewContext(false).WithHeaderInfo(header.Info{Time: time.Now()}) -} - -func (suite *SimTestSuite) getTestingAccounts(r *rand.Rand, n int) []simtypes.Account { - accounts := simtypes.RandomAccounts(r, n) - initAmt := sdk.TokensFromConsensusPower(200, sdk.DefaultPowerReduction) - initCoins := sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, initAmt)) - - // add coins to the accounts - for _, account := range accounts { - acc := suite.accountKeeper.NewAccountWithAddress(suite.ctx, account.Address) - suite.accountKeeper.SetAccount(suite.ctx, acc) - err := banktestutil.FundAccount(suite.ctx, suite.bankKeeper, account.Address, initCoins) - suite.Require().NoError(err) - } - - return accounts -} - -func (suite *SimTestSuite) TestWeightedOperations() { - require := suite.Require() - - appParams := make(simtypes.AppParams) - - weightedOps := simulation.WeightedOperations( - appParams, suite.txConfig, suite.accountKeeper, - suite.bankKeeper, suite.feegrantKeeper, - ) - - s := rand.NewSource(1) - r := rand.New(s) - accs := suite.getTestingAccounts(r, 3) - - expected := []struct { - weight int - opMsgRoute string - opMsgName string - }{ - { - simulation.DefaultWeightGrantAllowance, - feegrant.ModuleName, - sdk.MsgTypeURL(&feegrant.MsgGrantAllowance{}), - }, - { - simulation.DefaultWeightRevokeAllowance, - feegrant.ModuleName, - sdk.MsgTypeURL(&feegrant.MsgRevokeAllowance{}), - }, - } - - for i, w := range weightedOps { - operationMsg, _, err := w.Op()(r, suite.app.BaseApp, suite.ctx.WithHeaderInfo(header.Info{Time: time.Now()}), accs, suite.ctx.ChainID()) - require.NoError(err) - - // the following checks are very much dependent from the ordering of the output given - // by WeightedOperations. if the ordering in WeightedOperations changes some tests - // will fail - require.Equal(expected[i].weight, w.Weight(), "weight should be the same") - require.Equal(expected[i].opMsgRoute, operationMsg.Route, "route should be the same") - require.Equal(expected[i].opMsgName, operationMsg.Name, "operation Msg name should be the same") - } -} - -func (suite *SimTestSuite) TestSimulateMsgGrantAllowance() { - app, ctx := suite.app, suite.ctx - require := suite.Require() - - s := rand.NewSource(1) - r := rand.New(s) - accounts := suite.getTestingAccounts(r, 3) - addr1, err := suite.accountKeeper.AddressCodec().BytesToString(accounts[1].Address) - require.NoError(err) - addr2, err := suite.accountKeeper.AddressCodec().BytesToString(accounts[2].Address) - require.NoError(err) - - // execute operation - op := simulation.SimulateMsgGrantAllowance(suite.txConfig, suite.accountKeeper, suite.bankKeeper, suite.feegrantKeeper) - operationMsg, futureOperations, err := op(r, app.BaseApp, ctx.WithHeaderInfo(header.Info{Time: time.Now()}), accounts, "") - require.NoError(err) - - var msg feegrant.MsgGrantAllowance - err = proto.Unmarshal(operationMsg.Msg, &msg) - require.NoError(err) - require.True(operationMsg.OK) - require.Equal(addr2, msg.Granter) - require.Equal(addr1, msg.Grantee) - require.Len(futureOperations, 0) -} - -func (suite *SimTestSuite) TestSimulateMsgRevokeAllowance() { - app, ctx := suite.app, suite.ctx - require := suite.Require() - - s := rand.NewSource(1) - r := rand.New(s) - accounts := suite.getTestingAccounts(r, 3) - - feeAmt := sdk.TokensFromConsensusPower(200000, sdk.DefaultPowerReduction) - feeCoins := sdk.NewCoins(sdk.NewCoin("foo", feeAmt)) - - granter, grantee := accounts[0], accounts[1] - - oneYear := ctx.HeaderInfo().Time.AddDate(1, 0, 0) - err := suite.feegrantKeeper.GrantAllowance( - ctx, - granter.Address, - grantee.Address, - &feegrant.BasicAllowance{ - SpendLimit: feeCoins, - Expiration: &oneYear, - }, - ) - require.NoError(err) - - granterStr, err := suite.accountKeeper.AddressCodec().BytesToString(accounts[0].Address) - require.NoError(err) - granteeStr, err := suite.accountKeeper.AddressCodec().BytesToString(accounts[1].Address) - require.NoError(err) - - // execute operation - op := simulation.SimulateMsgRevokeAllowance(suite.txConfig, suite.accountKeeper, suite.bankKeeper, suite.feegrantKeeper) - operationMsg, futureOperations, err := op(r, app.BaseApp, ctx, accounts, "") - require.NoError(err) - - var msg feegrant.MsgRevokeAllowance - err = proto.Unmarshal(operationMsg.Msg, &msg) - require.NoError(err) - require.True(operationMsg.OK) - require.Equal(granterStr, msg.Granter) - require.Equal(granteeStr, msg.Grantee) - require.Len(futureOperations, 0) -} - -func TestSimTestSuite(t *testing.T) { - suite.Run(t, new(SimTestSuite)) -} diff --git a/tests/sims/gov/operations_test.go b/tests/sims/gov/operations_test.go deleted file mode 100644 index 95f99f33ab19..000000000000 --- a/tests/sims/gov/operations_test.go +++ /dev/null @@ -1,428 +0,0 @@ -package simulation_test - -import ( - "context" - "fmt" - "math/rand" - "testing" - "time" - - "github.com/cosmos/gogoproto/proto" - "github.com/stretchr/testify/require" - - "cosmossdk.io/core/address" - "cosmossdk.io/core/header" - "cosmossdk.io/depinject" - "cosmossdk.io/log" - _ "cosmossdk.io/x/accounts" - _ "cosmossdk.io/x/bank" - bankkeeper "cosmossdk.io/x/bank/keeper" - "cosmossdk.io/x/bank/testutil" - _ "cosmossdk.io/x/consensus" - _ "cosmossdk.io/x/gov" - "cosmossdk.io/x/gov/keeper" - "cosmossdk.io/x/gov/simulation" - "cosmossdk.io/x/gov/types" - v1 "cosmossdk.io/x/gov/types/v1" - "cosmossdk.io/x/gov/types/v1beta1" - _ "cosmossdk.io/x/protocolpool" - _ "cosmossdk.io/x/staking" - stakingkeeper "cosmossdk.io/x/staking/keeper" - - "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/runtime" - "github.com/cosmos/cosmos-sdk/testutil/configurator" - simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" - sdk "github.com/cosmos/cosmos-sdk/types" - simtypes "github.com/cosmos/cosmos-sdk/types/simulation" - _ "github.com/cosmos/cosmos-sdk/x/auth" - authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper" - _ "github.com/cosmos/cosmos-sdk/x/auth/tx/config" -) - -var ( - _ simtypes.WeightedProposalMsg = MockWeightedProposals{} - _ simtypes.WeightedProposalContent = MockWeightedProposals{} //nolint:staticcheck // testing legacy code path -) - -type MockWeightedProposals struct { - n int -} - -func (m MockWeightedProposals) AppParamsKey() string { - return fmt.Sprintf("AppParamsKey-%d", m.n) -} - -func (m MockWeightedProposals) DefaultWeight() int { - return m.n -} - -func (m MockWeightedProposals) MsgSimulatorFn() simtypes.MsgSimulatorFnX { - return func(_ context.Context, r *rand.Rand, _ []simtypes.Account, _ address.Codec) (sdk.Msg, error) { - return nil, nil - } -} - -func (m MockWeightedProposals) ContentSimulatorFn() simtypes.ContentSimulatorFn { //nolint:staticcheck // testing legacy code path - return func(r *rand.Rand, _ sdk.Context, _ []simtypes.Account) simtypes.Content { //nolint:staticcheck // testing legacy code path - return v1beta1.NewTextProposal( - fmt.Sprintf("title-%d: %s", m.n, simtypes.RandStringOfLength(r, 100)), - fmt.Sprintf("description-%d: %s", m.n, simtypes.RandStringOfLength(r, 4000)), - ) - } -} - -func mockWeightedProposalMsg(n int) []simtypes.WeightedProposalMsg { - wpc := make([]simtypes.WeightedProposalMsg, n) - for i := 0; i < n; i++ { - wpc[i] = MockWeightedProposals{i} - } - return wpc -} - -func mockWeightedLegacyProposalContent(n int) []simtypes.WeightedProposalContent { //nolint:staticcheck // testing legacy code path - wpc := make([]simtypes.WeightedProposalContent, n) //nolint:staticcheck // testing legacy code path - for i := 0; i < n; i++ { - wpc[i] = MockWeightedProposals{i} - } - return wpc -} - -// TestWeightedOperations tests the weights of the operations. -func TestWeightedOperations(t *testing.T) { - suite, ctx := createTestSuite(t, false) - app := suite.App - ctx.WithChainID("test-chain") - appParams := make(simtypes.AppParams) - - weightesOps := simulation.WeightedOperations(appParams, suite.TxConfig, suite.AccountKeeper, - suite.BankKeeper, suite.GovKeeper, mockWeightedProposalMsg(3), mockWeightedLegacyProposalContent(1), - ) - - // setup 3 accounts - s := rand.NewSource(1) - r := rand.New(s) - accs := getTestingAccounts(t, r, suite.AccountKeeper, suite.BankKeeper, suite.StakingKeeper, ctx, 3) - - expected := []struct { - weight int - opMsgRoute string - opMsgName string - }{ - {simulation.DefaultWeightMsgDeposit, types.ModuleName, simulation.TypeMsgDeposit}, - {simulation.DefaultWeightMsgVote, types.ModuleName, simulation.TypeMsgVote}, - {simulation.DefaultWeightMsgVoteWeighted, types.ModuleName, simulation.TypeMsgVoteWeighted}, - {simulation.DefaultWeightMsgCancelProposal, types.ModuleName, simulation.TypeMsgCancelProposal}, - {0, types.ModuleName, simulation.TypeMsgSubmitProposal}, - {1, types.ModuleName, simulation.TypeMsgSubmitProposal}, - {2, types.ModuleName, simulation.TypeMsgSubmitProposal}, - {0, types.ModuleName, simulation.TypeMsgSubmitProposal}, - } - - require.Equal(t, len(weightesOps), len(expected), "number of operations should be the same") - for i, w := range weightesOps { - operationMsg, _, err := w.Op()(r, app.BaseApp, ctx, accs, ctx.ChainID()) - require.NoError(t, err) - - // the following checks are very much dependent from the ordering of the output given - // by WeightedOperations. if the ordering in WeightedOperations changes some tests - // will fail - require.Equal(t, expected[i].weight, w.Weight(), "weight should be the same") - require.Equal(t, expected[i].opMsgRoute, operationMsg.Route, "route should be the same") - require.Equal(t, expected[i].opMsgName, operationMsg.Name, "operation Msg name should be the same") - } -} - -// TestSimulateMsgSubmitProposal tests the normal scenario of a valid message of type TypeMsgSubmitProposal. -// Abnormal scenarios, where errors occur, are not tested here. -func TestSimulateMsgSubmitProposal(t *testing.T) { - suite, ctx := createTestSuite(t, false) - app := suite.App - - // setup 3 accounts - s := rand.NewSource(1) - r := rand.New(s) - accounts := getTestingAccounts(t, r, suite.AccountKeeper, suite.BankKeeper, suite.StakingKeeper, ctx, 3) - - // execute operation - op := simulation.SimulateMsgSubmitProposal(suite.TxConfig, suite.AccountKeeper, suite.BankKeeper, suite.GovKeeper, MockWeightedProposals{3}.MsgSimulatorFn()) - operationMsg, _, err := op(r, app.BaseApp, ctx, accounts, "") - require.NoError(t, err) - - var msg v1.MsgSubmitProposal - err = proto.Unmarshal(operationMsg.Msg, &msg) - require.NoError(t, err) - require.True(t, operationMsg.OK) - require.Equal(t, "cosmos1ghekyjucln7y67ntx7cf27m9dpuxxemn4c8g4r", msg.Proposer) - require.NotEqual(t, len(msg.InitialDeposit), 0) - require.Equal(t, "47841094stake", msg.InitialDeposit[0].String()) - require.Equal(t, simulation.TypeMsgSubmitProposal, sdk.MsgTypeURL(&msg)) -} - -// TestSimulateMsgSubmitLegacyProposal tests the normal scenario of a valid message of type TypeMsgSubmitProposal. -// Abnormal scenarios, where errors occur, are not tested here. -func TestSimulateMsgSubmitLegacyProposal(t *testing.T) { - suite, ctx := createTestSuite(t, false) - app := suite.App - - // setup 3 accounts - s := rand.NewSource(1) - r := rand.New(s) - accounts := getTestingAccounts(t, r, suite.AccountKeeper, suite.BankKeeper, suite.StakingKeeper, ctx, 3) - - // execute operation - op := simulation.SimulateMsgSubmitLegacyProposal(suite.TxConfig, suite.AccountKeeper, suite.BankKeeper, suite.GovKeeper, MockWeightedProposals{3}.ContentSimulatorFn()) - operationMsg, _, err := op(r, app.BaseApp, ctx, accounts, "") - require.NoError(t, err) - - var msg v1.MsgSubmitProposal - err = proto.Unmarshal(operationMsg.Msg, &msg) - require.NoError(t, err) - var msgLegacyContent v1.MsgExecLegacyContent - err = proto.Unmarshal(msg.Messages[0].Value, &msgLegacyContent) - require.NoError(t, err) - var textProposal v1beta1.TextProposal - err = proto.Unmarshal(msgLegacyContent.Content.Value, &textProposal) - require.NoError(t, err) - - require.True(t, operationMsg.OK) - require.Equal(t, "cosmos1p8wcgrjr4pjju90xg6u9cgq55dxwq8j7u4x9a0", msg.Proposer) - require.NotEqual(t, len(msg.InitialDeposit), 0) - require.Equal(t, "25166256stake", msg.InitialDeposit[0].String()) - require.Equal(t, "title-3: ZBSpYuLyYggwexjxusrBqDOTtGTOWeLrQKjLxzIivHSlcxgdXhhuTSkuxKGLwQvuyNhYFmBZHeAerqyNEUzXPFGkqEGqiQWIXnku", - textProposal.GetTitle()) - require.Equal(t, "description-3: NJWzHdBNpAXKJPHWQdrGYcAHSctgVlqwqHoLfHsXUdStwfefwzqLuKEhmMyYLdbZrcPgYqjNHxPexsruwEGStAneKbWkQDDIlCWBLSiAASNhZqNFlPtfqPJoxKsgMdzjWqLWdqKQuJqWPMvwPQWZUtVMOTMYKJbfdlZsjdsomuScvDmbDkgRualsxDvRJuCAmPOXitIbcyWsKGSdrEunFAOdmXnsuyFVgJqEjbklvmwrUlsxjRSfKZxGcpayDdgoFcnVSutxjRgOSFzPwidAjubMncNweqpbxhXGchpZUxuFDOtpnhNUycJICRYqsPhPSCjPTWZFLkstHWJxvdPEAyEIxXgLwbNOjrgzmaujiBABBIXvcXpLrbcEWNNQsbjvgJFgJkflpRohHUutvnaUqoopuKjTDaemDeSdqbnOzcfJpcTuAQtZoiLZOoAIlboFDAeGmSNwkvObPRvRWQgWkGkxwtPauYgdkmypLjbqhlHJIQTntgWjXwZdOyYEdQRRLfMSdnxqppqUofqLbLQDUjwKVKfZJUJQPsWIPwIVaSTrmKskoAhvmZyJgeRpkaTfGgrJzAigcxtfshmiDCFkuiluqtMOkidknnTBtumyJYlIsWLnCQclqdVmikUoMOPdPWwYbJxXyqUVicNxFxyqJTenNblyyKSdlCbiXxUiYUiMwXZASYfvMDPFgxniSjWaZTjHkqlJvtBsXqwPpyVxnJVGFWhfSxgOcduoxkiopJvFjMmFabrGYeVtTXLhxVUEiGwYUvndjFGzDVntUvibiyZhfMQdMhgsiuysLMiePBNXifRLMsSmXPkwlPloUbJveCvUlaalhZHuvdkCnkSHbMbmOnrfEGPwQiACiPlnihiaOdbjPqPiTXaHDoJXjSlZmltGqNHHNrcKdlFSCdmVOuvDcBLdSklyGJmcLTbSFtALdGlPkqqecJrpLCXNPWefoTJNgEJlyMEPneVaxxduAAEqQpHWZodWyRkDAxzyMnFMcjSVqeRXLqsNyNtQBbuRvunZflWSbbvXXdkyLikYqutQhLPONXbvhcQZJPSWnOulqQaXmbfFxAkqfYeseSHOQidHwbcsOaMnSrrmGjjRmEMQNuknupMxJiIeVjmgZvbmjPIQTEhQFULQLBMPrxcFPvBinaOPYWGvYGRKxLZdwamfRQQFngcdSlvwjfaPbURasIsGJVHtcEAxnIIrhSriiXLOlbEBLXFElXJFGxHJczRBIxAuPKtBisjKBwfzZFagdNmjdwIRvwzLkFKWRTDPxJCmpzHUcrPiiXXHnOIlqNVoGSXZewdnCRhuxeYGPVTfrNTQNOxZmxInOazUYNTNDgzsxlgiVEHPKMfbesvPHUqpNkUqbzeuzfdrsuLDpKHMUbBMKczKKWOdYoIXoPYtEjfOnlQLoGnbQUCuERdEFaptwnsHzTJDsuZkKtzMpFaZobynZdzNydEeJJHDYaQcwUxcqvwfWwNUsCiLvkZQiSfzAHftYgAmVsXgtmcYgTqJIawstRYJrZdSxlfRiqTufgEQVambeZZmaAyRQbcmdjVUZZCgqDrSeltJGXPMgZnGDZqISrGDOClxXCxMjmKqEPwKHoOfOeyGmqWqihqjINXLqnyTesZePQRqaWDQNqpLgNrAUKulklmckTijUltQKuWQDwpLmDyxLppPVMwsmBIpOwQttYFMjgJQZLYFPmxWFLIeZihkRNnkzoypBICIxgEuYsVWGIGRbbxqVasYnstWomJnHwmtOhAFSpttRYYzBmyEtZXiCthvKvWszTXDbiJbGXMcrYpKAgvUVFtdKUfvdMfhAryctklUCEdjetjuGNfJjajZtvzdYaqInKtFPPLYmRaXPdQzxdSQfmZDEVHlHGEGNSPRFJuIfKLLfUmnHxHnRjmzQPNlqrXgifUdzAGKVabYqvcDeYoTYgPsBUqehrBhmQUgTvDnsdpuhUoxskDdppTsYMcnDIPSwKIqhXDCIxOuXrywahvVavvHkPuaenjLmEbMgrkrQLHEAwrhHkPRNvonNQKqprqOFVZKAtpRSpvQUxMoXCMZLSSbnLEFsjVfANdQNQVwTmGxqVjVqRuxREAhuaDrFgEZpYKhwWPEKBevBfsOIcaZKyykQafzmGPLRAKDtTcJxJVgiiuUkmyMYuDUNEUhBEdoBLJnamtLmMJQgmLiUELIhLpiEvpOXOvXCPUeldLFqkKOwfacqIaRcnnZvERKRMCKUkMABbDHytQqQblrvoxOZkwzosQfDKGtIdfcXRJNqlBNwOCWoQBcEWyqrMlYZIAXYJmLfnjoJepgSFvrgajaBAIksoyeHqgqbGvpAstMIGmIhRYGGNPRIfOQKsGoKgxtsidhTaAePRCBFqZgPDWCIkqOJezGVkjfYUCZTlInbxBXwUAVRsxHTQtJFnnpmMvXDYCVlEmnZBKhmmxQOIQzxFWpJQkQoSAYzTEiDWEOsVLNrbfzeHFRyeYATakQQWmFDLPbVMCJcWjFGJjfqCoVzlbNNEsqxdSmNPjTjHYOkuEMFLkXYGaoJlraLqayMeCsTjWNRDPBywBJLAPVkGQqTwApVVwYAetlwSbzsdHWsTwSIcctkyKDuRWYDQikRqsKTMJchrliONJeaZIzwPQrNbTwxsGdwuduvibtYndRwpdsvyCktRHFalvUuEKMqXbItfGcNGWsGzubdPMYayOUOINjpcFBeESdwpdlTYmrPsLsVDhpTzoMegKrytNVZkfJRPuDCUXxSlSthOohmsuxmIZUedzxKmowKOdXTMcEtdpHaPWgIsIjrViKrQOCONlSuazmLuCUjLltOGXeNgJKedTVrrVCpWYWHyVrdXpKgNaMJVjbXxnVMSChdWKuZdqpisvrkBJPoURDYxWOtpjzZoOpWzyUuYNhCzRoHsMjmmWDcXzQiHIyjwdhPNwiPqFxeUfMVFQGImhykFgMIlQEoZCaRoqSBXTSWAeDumdbsOGtATwEdZlLfoBKiTvodQBGOEcuATWXfiinSjPmJKcWgQrTVYVrwlyMWhxqNbCMpIQNoSMGTiWfPTCezUjYcdWppnsYJihLQCqbNLRGgqrwHuIvsazapTpoPZIyZyeeSueJuTIhpHMEJfJpScshJubJGfkusuVBgfTWQoywSSliQQSfbvaHKiLnyjdSbpMkdBgXepoSsHnCQaYuHQqZsoEOmJCiuQUpJkmfyfbIShzlZpHFmLCsbknEAkKXKfRTRnuwdBeuOGgFbJLbDksHVapaRayWzwoYBEpmrlAxrUxYMUekKbpjPNfjUCjhbdMAnJmYQVZBQZkFVweHDAlaqJjRqoQPoOMLhyvYCzqEuQsAFoxWrzRnTVjStPadhsESlERnKhpEPsfDxNvxqcOyIulaCkmPdambLHvGhTZzysvqFauEgkFRItPfvisehFmoBhQqmkfbHVsgfHXDPJVyhwPllQpuYLRYvGodxKjkarnSNgsXoKEMlaSKxKdcVgvOkuLcfLFfdtXGTclqfPOfeoVLbqcjcXCUEBgAGplrkgsmIEhWRZLlGPGCwKWRaCKMkBHTAcypUrYjWwCLtOPVygMwMANGoQwFnCqFrUGMCRZUGJKTZIGPyldsifauoMnJPLTcDHmilcmahlqOELaAUYDBuzsVywnDQfwRLGIWozYaOAilMBcObErwgTDNGWnwQMUgFFSKtPDMEoEQCTKVREqrXZSGLqwTMcxHfWotDllNkIJPMbXzjDVjPOOjCFuIvTyhXKLyhUScOXvYthRXpPfKwMhptXaxIxgqBoUqzrWbaoLTVpQoottZyPFfNOoMioXHRuFwMRYUiKvcWPkrayyTLOCFJlAyslDameIuqVAuxErqFPEWIScKpBORIuZqoXlZuTvAjEdlEWDODFRregDTqGNoFBIHxvimmIZwLfFyKUfEWAnNBdtdzDmTPXtpHRGdIbuucfTjOygZsTxPjfweXhSUkMhPjMaxKlMIJMOXcnQfyzeOcbWwNbeH", - textProposal.GetDescription()) - require.Equal(t, simulation.TypeMsgSubmitProposal, sdk.MsgTypeURL(&msg)) -} - -// TestSimulateMsgCancelProposal tests the normal scenario of a valid message of type TypeMsgCancelProposal. -// Abnormal scenarios, where errors occur, are not tested here. -func TestSimulateMsgCancelProposal(t *testing.T) { - suite, ctx := createTestSuite(t, false) - app := suite.App - blockTime := time.Now().UTC() - ctx = ctx.WithHeaderInfo(header.Info{Time: blockTime}) - - // setup 3 accounts - s := rand.NewSource(1) - r := rand.New(s) - accounts := getTestingAccounts(t, r, suite.AccountKeeper, suite.BankKeeper, suite.StakingKeeper, ctx, 3) - // setup a proposal - proposer, err := suite.AccountKeeper.AddressCodec().BytesToString(accounts[0].Address) - require.NoError(t, err) - content := v1beta1.NewTextProposal("Test", "description") - contentMsg, err := v1.NewLegacyContent(content, suite.GovKeeper.GetGovernanceAccount(ctx).GetAddress().String()) - require.NoError(t, err) - - submitTime := ctx.HeaderInfo().Time - params, _ := suite.GovKeeper.Params.Get(ctx) - depositPeriod := params.MaxDepositPeriod - - proposal, err := v1.NewProposal([]sdk.Msg{contentMsg}, 1, submitTime, submitTime.Add(*depositPeriod), "", "title", "summary", proposer, v1.ProposalType_PROPOSAL_TYPE_STANDARD) - require.NoError(t, err) - - err = suite.GovKeeper.Proposals.Set(ctx, proposal.Id, proposal) - require.NoError(t, err) - - // execute operation - op := simulation.SimulateMsgCancelProposal(suite.TxConfig, suite.AccountKeeper, suite.BankKeeper, suite.GovKeeper) - operationMsg, _, err := op(r, app.BaseApp, ctx, accounts, "") - require.NoError(t, err) - - var msg v1.MsgCancelProposal - err = proto.Unmarshal(operationMsg.Msg, &msg) - require.NoError(t, err) - require.NoError(t, err) - require.True(t, operationMsg.OK) - require.Equal(t, uint64(1), msg.ProposalId) - require.Equal(t, proposer, msg.Proposer) - require.Equal(t, simulation.TypeMsgCancelProposal, sdk.MsgTypeURL(&msg)) -} - -// TestSimulateMsgDeposit tests the normal scenario of a valid message of type TypeMsgDeposit. -// Abnormal scenarios, where errors occur, are not tested here. -func TestSimulateMsgDeposit(t *testing.T) { - suite, ctx := createTestSuite(t, false) - app := suite.App - blockTime := time.Now().UTC() - ctx = ctx.WithHeaderInfo(header.Info{Time: blockTime}) - - // setup 3 accounts - s := rand.NewSource(1) - r := rand.New(s) - accounts := getTestingAccounts(t, r, suite.AccountKeeper, suite.BankKeeper, suite.StakingKeeper, ctx, 3) - - // setup a proposal - content := v1beta1.NewTextProposal("Test", "description") - contentMsg, err := v1.NewLegacyContent(content, suite.GovKeeper.GetGovernanceAccount(ctx).GetAddress().String()) - require.NoError(t, err) - - submitTime := ctx.HeaderInfo().Time - params, _ := suite.GovKeeper.Params.Get(ctx) - depositPeriod := params.MaxDepositPeriod - - proposal, err := v1.NewProposal([]sdk.Msg{contentMsg}, 1, submitTime, submitTime.Add(*depositPeriod), "", "text proposal", "description", "cosmos1ghekyjucln7y67ntx7cf27m9dpuxxemn4c8g4r", v1.ProposalType_PROPOSAL_TYPE_STANDARD) - require.NoError(t, err) - - err = suite.GovKeeper.Proposals.Set(ctx, proposal.Id, proposal) - require.NoError(t, err) - - // execute operation - op := simulation.SimulateMsgDeposit(suite.TxConfig, suite.AccountKeeper, suite.BankKeeper, suite.GovKeeper, simulation.NewSharedState()) - operationMsg, _, err := op(r, app.BaseApp, ctx, accounts, "") - require.NoError(t, err) - - var msg v1.MsgDeposit - err = proto.Unmarshal(operationMsg.Msg, &msg) - require.NoError(t, err) - require.True(t, operationMsg.OK) - require.Equal(t, uint64(1), msg.ProposalId) - require.Equal(t, "cosmos1ghekyjucln7y67ntx7cf27m9dpuxxemn4c8g4r", msg.Depositor) - require.NotEqual(t, len(msg.Amount), 0) - require.Equal(t, "560969stake", msg.Amount[0].String()) - require.Equal(t, simulation.TypeMsgDeposit, sdk.MsgTypeURL(&msg)) -} - -// TestSimulateMsgVote tests the normal scenario of a valid message of type TypeMsgVote. -// Abnormal scenarios, where errors occur, are not tested here. -func TestSimulateMsgVote(t *testing.T) { - suite, ctx := createTestSuite(t, false) - app := suite.App - blockTime := time.Now().UTC() - ctx = ctx.WithHeaderInfo(header.Info{Time: blockTime}) - - // setup 3 accounts - s := rand.NewSource(1) - r := rand.New(s) - accounts := getTestingAccounts(t, r, suite.AccountKeeper, suite.BankKeeper, suite.StakingKeeper, ctx, 3) - - // setup a proposal - govAcc := suite.GovKeeper.GetGovernanceAccount(ctx).GetAddress().String() - contentMsg, err := v1.NewLegacyContent(v1beta1.NewTextProposal("Test", "description"), govAcc) - require.NoError(t, err) - - submitTime := ctx.HeaderInfo().Time - params, _ := suite.GovKeeper.Params.Get(ctx) - depositPeriod := params.MaxDepositPeriod - - proposal, err := v1.NewProposal([]sdk.Msg{contentMsg}, 1, submitTime, submitTime.Add(*depositPeriod), "", "text proposal", "description", "cosmos1ghekyjucln7y67ntx7cf27m9dpuxxemn4c8g4r", v1.ProposalType_PROPOSAL_TYPE_STANDARD) - require.NoError(t, err) - - err = suite.GovKeeper.ActivateVotingPeriod(ctx, proposal) - require.NoError(t, err) - - // execute operation - op := simulation.SimulateMsgVote(suite.TxConfig, suite.AccountKeeper, suite.BankKeeper, suite.GovKeeper, simulation.NewSharedState()) - operationMsg, _, err := op(r, app.BaseApp, ctx, accounts, "") - require.NoError(t, err) - - var msg v1.MsgVote - err = proto.Unmarshal(operationMsg.Msg, &msg) - require.NoError(t, err) - require.True(t, operationMsg.OK) - require.Equal(t, uint64(1), msg.ProposalId) - require.Equal(t, "cosmos1ghekyjucln7y67ntx7cf27m9dpuxxemn4c8g4r", msg.Voter) - require.Equal(t, v1.OptionYes, msg.Option) - require.Equal(t, simulation.TypeMsgVote, sdk.MsgTypeURL(&msg)) -} - -// TestSimulateMsgVoteWeighted tests the normal scenario of a valid message of type TypeMsgVoteWeighted. -// Abnormal scenarios, where errors occur, are not tested here. -func TestSimulateMsgVoteWeighted(t *testing.T) { - suite, ctx := createTestSuite(t, false) - app := suite.App - blockTime := time.Now().UTC() - ctx = ctx.WithHeaderInfo(header.Info{Time: blockTime}) - - // setup 3 accounts - s := rand.NewSource(1) - r := rand.New(s) - accounts := getTestingAccounts(t, r, suite.AccountKeeper, suite.BankKeeper, suite.StakingKeeper, ctx, 3) - - // setup a proposal - govAcc := suite.GovKeeper.GetGovernanceAccount(ctx).GetAddress().String() - contentMsg, err := v1.NewLegacyContent(v1beta1.NewTextProposal("Test", "description"), govAcc) - require.NoError(t, err) - submitTime := ctx.HeaderInfo().Time - params, _ := suite.GovKeeper.Params.Get(ctx) - depositPeriod := params.MaxDepositPeriod - - proposal, err := v1.NewProposal([]sdk.Msg{contentMsg}, 1, submitTime, submitTime.Add(*depositPeriod), "", "text proposal", "test", "cosmos1ghekyjucln7y67ntx7cf27m9dpuxxemn4c8g4r", v1.ProposalType_PROPOSAL_TYPE_STANDARD) - require.NoError(t, err) - - err = suite.GovKeeper.ActivateVotingPeriod(ctx, proposal) - require.NoError(t, err) - - // execute operation - op := simulation.SimulateMsgVoteWeighted(suite.TxConfig, suite.AccountKeeper, suite.BankKeeper, suite.GovKeeper, simulation.NewSharedState()) - operationMsg, _, err := op(r, app.BaseApp, ctx, accounts, "") - require.NoError(t, err) - - var msg v1.MsgVoteWeighted - err = proto.Unmarshal(operationMsg.Msg, &msg) - require.NoError(t, err) - require.True(t, operationMsg.OK) - require.Equal(t, uint64(1), msg.ProposalId) - require.Equal(t, "cosmos1ghekyjucln7y67ntx7cf27m9dpuxxemn4c8g4r", msg.Voter) - require.True(t, len(msg.Options) >= 1) - require.Equal(t, simulation.TypeMsgVoteWeighted, sdk.MsgTypeURL(&msg)) -} - -type suite struct { - TxConfig client.TxConfig - AccountKeeper authkeeper.AccountKeeper - BankKeeper bankkeeper.Keeper - GovKeeper *keeper.Keeper - StakingKeeper *stakingkeeper.Keeper - App *runtime.App -} - -// returns context and an app with updated mint keeper -func createTestSuite(t *testing.T, isCheckTx bool) (suite, sdk.Context) { - t.Helper() - res := suite{} - - app, err := simtestutil.Setup( - depinject.Configs( - configurator.NewAppConfig( - configurator.AccountsModule(), - configurator.AuthModule(), - configurator.TxModule(), - configurator.BankModule(), - configurator.StakingModule(), - configurator.ConsensusModule(), - configurator.GovModule(), - configurator.ProtocolPoolModule(), - ), - depinject.Supply(log.NewNopLogger()), - ), - &res.TxConfig, &res.AccountKeeper, &res.BankKeeper, &res.GovKeeper, &res.StakingKeeper) - require.NoError(t, err) - - ctx := app.BaseApp.NewContext(isCheckTx) - - res.App = app - return res, ctx -} - -func getTestingAccounts( - t *testing.T, r *rand.Rand, - accountKeeper authkeeper.AccountKeeper, bankKeeper bankkeeper.Keeper, stakingKeeper *stakingkeeper.Keeper, - ctx sdk.Context, n int, -) []simtypes.Account { - t.Helper() - accounts := simtypes.RandomAccounts(r, n) - - initAmt := stakingKeeper.TokensFromConsensusPower(ctx, 200) - initCoins := sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, initAmt)) - - // add coins to the accounts - for _, account := range accounts { - acc := accountKeeper.NewAccountWithAddress(ctx, account.Address) - accountKeeper.SetAccount(ctx, acc) - require.NoError(t, testutil.FundAccount(ctx, bankKeeper, account.Address, initCoins)) - } - - return accounts -} diff --git a/tests/sims/nft/app_config.go b/tests/sims/nft/app_config.go deleted file mode 100644 index 7b3a4bb869b3..000000000000 --- a/tests/sims/nft/app_config.go +++ /dev/null @@ -1,27 +0,0 @@ -package nft - -import ( - _ "cosmossdk.io/x/accounts" // import as blank for app wiring - _ "cosmossdk.io/x/bank" // import as blank for app wiring - _ "cosmossdk.io/x/consensus" // import as blank for app wiring - _ "cosmossdk.io/x/mint" // import as blank for app wiring - _ "cosmossdk.io/x/nft/module" // import as blank for app wiring - _ "cosmossdk.io/x/staking" // import as blank for app wiring - - "github.com/cosmos/cosmos-sdk/testutil/configurator" - _ "github.com/cosmos/cosmos-sdk/x/auth" // import as blank for app wiring - _ "github.com/cosmos/cosmos-sdk/x/auth/tx/config" // import as blank for app wiring - _ "github.com/cosmos/cosmos-sdk/x/genutil" // import as blank for app wiring -) - -var AppConfig = configurator.NewAppConfig( - configurator.AccountsModule(), - configurator.AuthModule(), - configurator.BankModule(), - configurator.StakingModule(), - configurator.TxModule(), - configurator.ConsensusModule(), - configurator.GenutilModule(), - configurator.MintModule(), - configurator.NFTModule(), -) diff --git a/tests/sims/nft/operations_test.go b/tests/sims/nft/operations_test.go deleted file mode 100644 index 1fc693200c85..000000000000 --- a/tests/sims/nft/operations_test.go +++ /dev/null @@ -1,141 +0,0 @@ -package nft - -import ( - "math/rand" - "testing" - "time" - - "github.com/cosmos/gogoproto/proto" - "github.com/stretchr/testify/suite" - - "cosmossdk.io/core/header" - "cosmossdk.io/depinject" - "cosmossdk.io/log" - bankkeeper "cosmossdk.io/x/bank/keeper" - banktestutil "cosmossdk.io/x/bank/testutil" - "cosmossdk.io/x/nft" - nftkeeper "cosmossdk.io/x/nft/keeper" - "cosmossdk.io/x/nft/simulation" - stakingkeeper "cosmossdk.io/x/staking/keeper" - - "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/codec" - codectypes "github.com/cosmos/cosmos-sdk/codec/types" - "github.com/cosmos/cosmos-sdk/runtime" - simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" - sdk "github.com/cosmos/cosmos-sdk/types" - simtypes "github.com/cosmos/cosmos-sdk/types/simulation" - authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper" -) - -type SimTestSuite struct { - suite.Suite - - ctx sdk.Context - - app *runtime.App - codec codec.Codec - interfaceRegistry codectypes.InterfaceRegistry - txConfig client.TxConfig - accountKeeper authkeeper.AccountKeeper - bankKeeper bankkeeper.Keeper - stakingKeeper *stakingkeeper.Keeper - nftKeeper nftkeeper.Keeper -} - -func (suite *SimTestSuite) SetupTest() { - app, err := simtestutil.Setup( - depinject.Configs( - AppConfig, - depinject.Supply(log.NewNopLogger()), - ), - &suite.codec, - &suite.interfaceRegistry, - &suite.txConfig, - &suite.accountKeeper, - &suite.bankKeeper, - &suite.stakingKeeper, - &suite.nftKeeper, - ) - suite.Require().NoError(err) - - suite.app = app - suite.ctx = app.BaseApp.NewContext(false) -} - -func (suite *SimTestSuite) TestWeightedOperations() { - weightedOps := simulation.WeightedOperations( - suite.interfaceRegistry, - make(simtypes.AppParams), - suite.codec, - suite.txConfig, - suite.accountKeeper, - suite.bankKeeper, - suite.nftKeeper, - ) - - // setup 3 accounts - s := rand.NewSource(1) - r := rand.New(s) - accs := suite.getTestingAccounts(r, 3) - - expected := []struct { - weight int - opMsgRoute string - opMsgName string - }{ - {simulation.WeightSend, nft.ModuleName, simulation.TypeMsgSend}, - } - - for i, w := range weightedOps { - operationMsg, _, err := w.Op()(r, suite.app.BaseApp, suite.ctx, accs, "") - suite.Require().NoError(err) - - // the following checks are very much dependent from the ordering of the output given - // by WeightedOperations. if the ordering in WeightedOperations changes some tests - // will fail - suite.Require().Equal(expected[i].weight, w.Weight(), "weight should be the same") - suite.Require().Equal(expected[i].opMsgRoute, operationMsg.Route, "route should be the same") - suite.Require().Equal(expected[i].opMsgName, operationMsg.Name, "operation Msg name should be the same") - } -} - -func (suite *SimTestSuite) getTestingAccounts(r *rand.Rand, n int) []simtypes.Account { - accounts := simtypes.RandomAccounts(r, n) - - initAmt := suite.stakingKeeper.TokensFromConsensusPower(suite.ctx, 200000) - initCoins := sdk.NewCoins(sdk.NewCoin("stake", initAmt)) - - // add coins to the accounts - for _, account := range accounts { - acc := suite.accountKeeper.NewAccountWithAddress(suite.ctx, account.Address) - suite.accountKeeper.SetAccount(suite.ctx, acc) - suite.Require().NoError(banktestutil.FundAccount(suite.ctx, suite.bankKeeper, account.Address, initCoins)) - } - - return accounts -} - -func (suite *SimTestSuite) TestSimulateMsgSend() { - s := rand.NewSource(1) - r := rand.New(s) - accounts := suite.getTestingAccounts(r, 2) - blockTime := time.Now().UTC() - ctx := suite.ctx.WithHeaderInfo(header.Info{Time: blockTime}) - - // execute operation - registry := suite.interfaceRegistry - op := simulation.SimulateMsgSend(codec.NewProtoCodec(registry), suite.txConfig, suite.accountKeeper, suite.bankKeeper, suite.nftKeeper) - operationMsg, futureOperations, err := op(r, suite.app.BaseApp, ctx, accounts, "") - suite.Require().NoError(err) - - var msg nft.MsgSend - err = proto.Unmarshal(operationMsg.Msg, &msg) - suite.Require().NoError(err) - suite.Require().True(operationMsg.OK) - suite.Require().Len(futureOperations, 0) -} - -func TestSimTestSuite(t *testing.T) { - suite.Run(t, new(SimTestSuite)) -} diff --git a/tests/sims/protocolpool/app_config.go b/tests/sims/protocolpool/app_config.go deleted file mode 100644 index d8b1ace75263..000000000000 --- a/tests/sims/protocolpool/app_config.go +++ /dev/null @@ -1,29 +0,0 @@ -package protocolpool - -import ( - _ "cosmossdk.io/x/accounts" // import as blank for app wiring - _ "cosmossdk.io/x/bank" // import as blank for app wiring - _ "cosmossdk.io/x/consensus" // import as blank for app wiring - _ "cosmossdk.io/x/distribution" // import as blank for app wiring - _ "cosmossdk.io/x/mint" // import as blank for app wiring - _ "cosmossdk.io/x/protocolpool" // import as blank for app wiring - _ "cosmossdk.io/x/staking" // import as blank for app wiring - - "github.com/cosmos/cosmos-sdk/testutil/configurator" - _ "github.com/cosmos/cosmos-sdk/x/auth" // import as blank for app wiring - _ "github.com/cosmos/cosmos-sdk/x/auth/tx/config" // import as blank for app wiring - _ "github.com/cosmos/cosmos-sdk/x/genutil" // import as blank for app wiring -) - -var AppConfig = configurator.NewAppConfig( - configurator.AccountsModule(), - configurator.AuthModule(), - configurator.BankModule(), - configurator.StakingModule(), - configurator.TxModule(), - configurator.ConsensusModule(), - configurator.GenutilModule(), - configurator.DistributionModule(), - configurator.MintModule(), - configurator.ProtocolPoolModule(), -) diff --git a/tests/sims/protocolpool/operations_test.go b/tests/sims/protocolpool/operations_test.go deleted file mode 100644 index dffebefd97b6..000000000000 --- a/tests/sims/protocolpool/operations_test.go +++ /dev/null @@ -1,148 +0,0 @@ -package protocolpool - -import ( - "math/rand" - "testing" - - "github.com/cosmos/gogoproto/proto" - "github.com/stretchr/testify/require" - - "cosmossdk.io/depinject" - "cosmossdk.io/log" - bankkeeper "cosmossdk.io/x/bank/keeper" - banktestutil "cosmossdk.io/x/bank/testutil" - "cosmossdk.io/x/protocolpool/keeper" - "cosmossdk.io/x/protocolpool/simulation" - "cosmossdk.io/x/protocolpool/types" - stakingkeeper "cosmossdk.io/x/staking/keeper" - - "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/codec" - "github.com/cosmos/cosmos-sdk/runtime" - simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" - sdk "github.com/cosmos/cosmos-sdk/types" - simtypes "github.com/cosmos/cosmos-sdk/types/simulation" - authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper" -) - -type suite struct { - Ctx sdk.Context - App *runtime.App - - TxConfig client.TxConfig - Cdc codec.Codec - AccountKeeper authkeeper.AccountKeeper - BankKeeper bankkeeper.Keeper - StakingKeeper *stakingkeeper.Keeper - PoolKeeper keeper.Keeper -} - -func setUpTest(t *testing.T) suite { - t.Helper() - res := suite{} - - var ( - appBuilder *runtime.AppBuilder - err error - ) - - app, err := simtestutil.Setup( - depinject.Configs( - AppConfig, - depinject.Supply(log.NewNopLogger()), - ), - &res.AccountKeeper, - &res.BankKeeper, - &res.Cdc, - &appBuilder, - &res.StakingKeeper, - &res.PoolKeeper, - &res.TxConfig, - ) - require.NoError(t, err) - - res.App = app - res.Ctx = app.BaseApp.NewContext(false) - return res -} - -// TestWeightedOperations tests the weights of the operations. -func TestWeightedOperations(t *testing.T) { - suite := setUpTest(t) - - appParams := make(simtypes.AppParams) - - weightedOps := simulation.WeightedOperations(appParams, suite.Cdc, suite.TxConfig, suite.AccountKeeper, - suite.BankKeeper, suite.PoolKeeper) - - // setup 3 accounts - s := rand.NewSource(1) - r := rand.New(s) - accs := getTestingAccounts(t, r, suite.AccountKeeper, suite.BankKeeper, suite.StakingKeeper, suite.Ctx, 3) - - expected := []struct { - weight int - opMsgRoute string - opMsgName string - }{ - {simulation.DefaultWeightMsgFundCommunityPool, types.ModuleName, sdk.MsgTypeURL(&types.MsgFundCommunityPool{})}, - } - - for i, w := range weightedOps { - operationMsg, _, err := w.Op()(r, suite.App.BaseApp, suite.Ctx, accs, "") - require.NoError(t, err) - - // the following checks are very much dependent from the ordering of the output given - // by WeightedOperations. if the ordering in WeightedOperations changes some tests - // will fail - require.Equal(t, expected[i].weight, w.Weight(), "weight should be the same") - require.Equal(t, expected[i].opMsgRoute, operationMsg.Route, "route should be the same") - require.Equal(t, expected[i].opMsgName, operationMsg.Name, "operation Msg name should be the same") - } -} - -// TestSimulateMsgFundCommunityPool tests the normal scenario of a valid message of type TypeMsgFundCommunityPool. -// Abonormal scenarios, where the message is created by an errors, are not tested here. -func TestSimulateMsgFundCommunityPool(t *testing.T) { - suite := setUpTest(t) - - // setup 3 accounts - s := rand.NewSource(1) - r := rand.New(s) - accounts := getTestingAccounts(t, r, suite.AccountKeeper, suite.BankKeeper, suite.StakingKeeper, suite.Ctx, 3) - - // execute operation - op := simulation.SimulateMsgFundCommunityPool(suite.TxConfig, suite.AccountKeeper, suite.BankKeeper, suite.PoolKeeper) - operationMsg, futureOperations, err := op(r, suite.App.BaseApp, suite.Ctx, accounts, "") - require.NoError(t, err) - - var msg types.MsgFundCommunityPool - err = proto.Unmarshal(operationMsg.Msg, &msg) - require.NoError(t, err) - require.True(t, operationMsg.OK) - require.Equal(t, "4896096stake", msg.Amount.String()) - require.Equal(t, "cosmos1ghekyjucln7y67ntx7cf27m9dpuxxemn4c8g4r", msg.Depositor) - require.Equal(t, sdk.MsgTypeURL(&types.MsgFundCommunityPool{}), sdk.MsgTypeURL(&msg)) - require.Len(t, futureOperations, 0) -} - -func getTestingAccounts( - t *testing.T, r *rand.Rand, - accountKeeper authkeeper.AccountKeeper, bankKeeper bankkeeper.Keeper, - stakingKeeper *stakingkeeper.Keeper, ctx sdk.Context, n int, -) []simtypes.Account { - t.Helper() - accounts := simtypes.RandomAccounts(r, n) - - initAmt := stakingKeeper.TokensFromConsensusPower(ctx, 200) - initCoins := sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, initAmt)) - - // add coins to the accounts - for _, account := range accounts { - acc := accountKeeper.NewAccountWithAddress(ctx, account.Address) - accountKeeper.SetAccount(ctx, acc) - require.NoError(t, banktestutil.FundAccount(ctx, bankKeeper, account.Address, initCoins)) - } - - return accounts -} diff --git a/tests/sims/slashing/app_config.go b/tests/sims/slashing/app_config.go deleted file mode 100644 index f649e196fb75..000000000000 --- a/tests/sims/slashing/app_config.go +++ /dev/null @@ -1,31 +0,0 @@ -package slashing - -import ( - _ "cosmossdk.io/x/accounts" // import as blank for app wiring - _ "cosmossdk.io/x/bank" // import as blank for app wiring - _ "cosmossdk.io/x/consensus" // import as blank for app wiring - _ "cosmossdk.io/x/distribution" // import as blank for app wiring - _ "cosmossdk.io/x/mint" // import as blank for app wiring - _ "cosmossdk.io/x/protocolpool" // import as blank for app wiring - _ "cosmossdk.io/x/slashing" // import as blank for app wiring - _ "cosmossdk.io/x/staking" // import as blank for app wiring - - "github.com/cosmos/cosmos-sdk/testutil/configurator" - _ "github.com/cosmos/cosmos-sdk/x/auth" // import as blank for app wiring - _ "github.com/cosmos/cosmos-sdk/x/auth/tx/config" // import as blank for app wiring - _ "github.com/cosmos/cosmos-sdk/x/genutil" // import as blank for app wiring -) - -var AppConfig = configurator.NewAppConfig( - configurator.AccountsModule(), - configurator.AuthModule(), - configurator.BankModule(), - configurator.StakingModule(), - configurator.SlashingModule(), - configurator.TxModule(), - configurator.ConsensusModule(), - configurator.GenutilModule(), - configurator.MintModule(), - configurator.DistributionModule(), - configurator.ProtocolPoolModule(), -) diff --git a/tests/sims/slashing/operations_test.go b/tests/sims/slashing/operations_test.go deleted file mode 100644 index f4b6c31773bd..000000000000 --- a/tests/sims/slashing/operations_test.go +++ /dev/null @@ -1,228 +0,0 @@ -package slashing - -import ( - "fmt" - "math/rand" - "testing" - "time" - - abci "github.com/cometbft/cometbft/api/cometbft/abci/v1" - cmttypes "github.com/cometbft/cometbft/types" - "github.com/cosmos/gogoproto/proto" - "github.com/stretchr/testify/suite" - - "cosmossdk.io/collections" - "cosmossdk.io/core/header" - "cosmossdk.io/depinject" - "cosmossdk.io/log" - "cosmossdk.io/math" - bankkeeper "cosmossdk.io/x/bank/keeper" - banktestutil "cosmossdk.io/x/bank/testutil" - distributionkeeper "cosmossdk.io/x/distribution/keeper" - distrtypes "cosmossdk.io/x/distribution/types" - mintkeeper "cosmossdk.io/x/mint/keeper" - minttypes "cosmossdk.io/x/mint/types" - slashingkeeper "cosmossdk.io/x/slashing/keeper" - "cosmossdk.io/x/slashing/simulation" - "cosmossdk.io/x/slashing/types" - stakingkeeper "cosmossdk.io/x/staking/keeper" - stakingtypes "cosmossdk.io/x/staking/types" - - "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/codec" - codectypes "github.com/cosmos/cosmos-sdk/codec/types" - cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" - "github.com/cosmos/cosmos-sdk/runtime" - simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" - sdk "github.com/cosmos/cosmos-sdk/types" - simtypes "github.com/cosmos/cosmos-sdk/types/simulation" - authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper" -) - -type SimTestSuite struct { - suite.Suite - - ctx sdk.Context - r *rand.Rand - accounts []simtypes.Account - - app *runtime.App - codec codec.Codec - interfaceRegistry codectypes.InterfaceRegistry - txConfig client.TxConfig - accountKeeper authkeeper.AccountKeeper - bankKeeper bankkeeper.Keeper - stakingKeeper *stakingkeeper.Keeper - slashingKeeper slashingkeeper.Keeper - distrKeeper distributionkeeper.Keeper - mintKeeper mintkeeper.Keeper -} - -func (suite *SimTestSuite) SetupTest() { - s := rand.NewSource(1) - suite.r = rand.New(s) - accounts := simtypes.RandomAccounts(suite.r, 4) - - // create validator (non random as using a seed) - createValidator := func() (*cmttypes.ValidatorSet, error) { - account := accounts[0] - cmtPk, err := cryptocodec.ToCmtPubKeyInterface(account.ConsKey.PubKey()) - if err != nil { - return nil, fmt.Errorf("failed to create pubkey: %w", err) - } - - validator := cmttypes.NewValidator(cmtPk, 1) - - return cmttypes.NewValidatorSet([]*cmttypes.Validator{validator}), nil - } - - startupCfg := simtestutil.DefaultStartUpConfig() - startupCfg.ValidatorSet = createValidator - - app, err := simtestutil.SetupWithConfiguration( - depinject.Configs( - AppConfig, - depinject.Supply(log.NewNopLogger()), - ), - startupCfg, - &suite.codec, - &suite.interfaceRegistry, - &suite.txConfig, - &suite.accountKeeper, - &suite.bankKeeper, - &suite.stakingKeeper, - &suite.mintKeeper, - &suite.slashingKeeper, - &suite.distrKeeper, - ) - - suite.Require().NoError(err) - suite.app = app - suite.ctx = app.BaseApp.NewContext(false) - - // remove genesis validator account - suite.accounts = accounts[1:] - - initAmt := suite.stakingKeeper.TokensFromConsensusPower(suite.ctx, 200) - initCoins := sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, initAmt)) - - // add coins to the accounts - for _, account := range suite.accounts { - acc := suite.accountKeeper.NewAccountWithAddress(suite.ctx, account.Address) - suite.accountKeeper.SetAccount(suite.ctx, acc) - suite.Require().NoError(banktestutil.FundAccount(suite.ctx, suite.bankKeeper, account.Address, initCoins)) - } - suite.Require().NoError(suite.mintKeeper.Params.Set(suite.ctx, minttypes.DefaultParams())) - suite.Require().NoError(suite.mintKeeper.Minter.Set(suite.ctx, minttypes.DefaultInitialMinter())) -} - -func TestSimTestSuite(t *testing.T) { - suite.Run(t, new(SimTestSuite)) -} - -// TestWeightedOperations tests the weights of the operations. -func (suite *SimTestSuite) TestWeightedOperations() { - ctx := suite.ctx.WithChainID("test-chain") - appParams := make(simtypes.AppParams) - - expected := []struct { - weight int - opMsgRoute string - opMsgName string - }{ - {simulation.DefaultWeightMsgUnjail, types.ModuleName, sdk.MsgTypeURL(&types.MsgUnjail{})}, - } - - weightedOps := simulation.WeightedOperations(suite.interfaceRegistry, appParams, suite.codec, suite.txConfig, suite.accountKeeper, suite.bankKeeper, suite.slashingKeeper, suite.stakingKeeper) - for i, w := range weightedOps { - operationMsg, _, err := w.Op()(suite.r, suite.app.BaseApp, ctx, suite.accounts, ctx.ChainID()) - suite.Require().NoError(err) - - // the following checks are very much dependent from the ordering of the output given - // by WeightedOperations. if the ordering in WeightedOperations changes some tests - // will fail - suite.Require().Equal(expected[i].weight, w.Weight(), "weight should be the same") - suite.Require().Equal(expected[i].opMsgRoute, operationMsg.Route, "route should be the same") - suite.Require().Equal(expected[i].opMsgName, operationMsg.Name, "operation Msg name should be the same") - } -} - -// TestSimulateMsgUnjail tests the normal scenario of a valid message of type types.MsgUnjail. -// Abonormal scenarios, where the message is created by an errors, are not tested here. -func (suite *SimTestSuite) TestSimulateMsgUnjail() { - blockTime := time.Now().UTC() - ctx := suite.ctx.WithHeaderInfo(header.Info{Time: blockTime}) - - // setup accounts[0] as validator0 - validator0, err := getTestingValidator0(ctx, suite.stakingKeeper, suite.accounts) - suite.Require().NoError(err) - - // setup validator0 by consensus address - err = suite.stakingKeeper.SetValidatorByConsAddr(ctx, validator0) - suite.Require().NoError(err) - - val0ConsAddress, err := validator0.GetConsAddr() - suite.Require().NoError(err) - val0ConsAddressStr, err := suite.stakingKeeper.ConsensusAddressCodec().BytesToString(val0ConsAddress) - suite.Require().NoError(err) - info := types.NewValidatorSigningInfo(val0ConsAddressStr, int64(4), - time.Unix(2, 0), false, int64(10)) - err = suite.slashingKeeper.ValidatorSigningInfo.Set(ctx, val0ConsAddress, info) - suite.Require().NoError(err) - // put validator0 in jail - suite.Require().NoError(suite.stakingKeeper.Jail(ctx, val0ConsAddress)) - - // setup self delegation - delTokens := suite.stakingKeeper.TokensFromConsensusPower(ctx, 2) - validator0, issuedShares := validator0.AddTokensFromDel(delTokens) - val0AccAddress, err := sdk.ValAddressFromBech32(validator0.OperatorAddress) - suite.Require().NoError(err) - selfDelegation := stakingtypes.NewDelegation(suite.accounts[0].Address.String(), validator0.GetOperator(), issuedShares) - suite.Require().NoError(suite.stakingKeeper.SetDelegation(ctx, selfDelegation)) - suite.Require().NoError(suite.distrKeeper.DelegatorStartingInfo.Set(ctx, collections.Join(val0AccAddress, sdk.AccAddress(val0AccAddress)), distrtypes.NewDelegatorStartingInfo(2, math.LegacyOneDec(), 200))) - - // begin a new block - _, err = suite.app.FinalizeBlock(&abci.FinalizeBlockRequest{Height: suite.app.LastBlockHeight() + 1, Hash: suite.app.LastCommitID().Hash, Time: blockTime}) - suite.Require().NoError(err) - - // execute operation - op := simulation.SimulateMsgUnjail(codec.NewProtoCodec(suite.interfaceRegistry), suite.txConfig, suite.accountKeeper, suite.bankKeeper, suite.slashingKeeper, suite.stakingKeeper) - operationMsg, futureOperations, err := op(suite.r, suite.app.BaseApp, ctx, suite.accounts, "") - suite.Require().NoError(err) - - var msg types.MsgUnjail - err = proto.Unmarshal(operationMsg.Msg, &msg) - suite.Require().NoError(err) - suite.Require().True(operationMsg.OK) - suite.Require().Equal("cosmosvaloper1p8wcgrjr4pjju90xg6u9cgq55dxwq8j7epjs3u", msg.ValidatorAddr) - suite.Require().Len(futureOperations, 0) -} - -func getTestingValidator0(ctx sdk.Context, stakingKeeper *stakingkeeper.Keeper, accounts []simtypes.Account) (stakingtypes.Validator, error) { - commission0 := stakingtypes.NewCommission(math.LegacyZeroDec(), math.LegacyOneDec(), math.LegacyOneDec()) - return getTestingValidator(ctx, stakingKeeper, accounts, commission0, 0) -} - -func getTestingValidator(ctx sdk.Context, stakingKeeper *stakingkeeper.Keeper, accounts []simtypes.Account, commission stakingtypes.Commission, n int) (stakingtypes.Validator, error) { - account := accounts[n] - valPubKey := account.ConsKey.PubKey() - valAddr := sdk.ValAddress(account.PubKey.Address().Bytes()) - validator, err := stakingtypes.NewValidator(valAddr.String(), valPubKey, stakingtypes.Description{}) - if err != nil { - return stakingtypes.Validator{}, fmt.Errorf("failed to create validator: %w", err) - } - - validator, err = validator.SetInitialCommission(commission) - if err != nil { - return stakingtypes.Validator{}, fmt.Errorf("failed to set initial commission: %w", err) - } - - validator.DelegatorShares = math.LegacyNewDec(100) - validator.Tokens = math.NewInt(1000000) - - err = stakingKeeper.SetValidator(ctx, validator) - if err != nil { - return stakingtypes.Validator{}, err - } - return validator, nil -} diff --git a/tests/systemtests/authz_test.go b/tests/systemtests/authz_test.go new file mode 100644 index 000000000000..da66aef5d267 --- /dev/null +++ b/tests/systemtests/authz_test.go @@ -0,0 +1,867 @@ +//go:build system_test + +package systemtests + +import ( + "fmt" + "net/http" + "os" + "testing" + "time" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/tidwall/gjson" +) + +const ( + msgSendTypeURL = `/cosmos.bank.v1beta1.MsgSend` + msgDelegateTypeURL = `/cosmos.staking.v1beta1.MsgDelegate` + msgVoteTypeURL = `/cosmos.gov.v1.MsgVote` + msgUndelegateTypeURL = `/cosmos.staking.v1beta1.MsgUndelegate` + msgRedelegateTypeURL = `/cosmos.staking.v1beta1.MsgBeginRedelegate` + sendAuthzTypeURL = `/cosmos.bank.v1beta1.SendAuthorization` + genericAuthzTypeURL = `/cosmos.authz.v1beta1.GenericAuthorization` + testDenom = "stake" +) + +func TestAuthzGrantTxCmd(t *testing.T) { + // scenario: test authz grant command + // given a running chain + + sut.ResetChain(t) + cli := NewCLIWrapper(t, sut, verbose) + + // get validator address which will be used as granter + granterAddr := cli.GetKeyAddr("node0") + require.NotEmpty(t, granterAddr) + + // add grantee keys which will be used for each valid transaction + grantee1Addr := cli.AddKey("grantee1") + grantee2Addr := cli.AddKey("grantee2") + require.NotEqual(t, granterAddr, grantee2Addr) + grantee3Addr := cli.AddKey("grantee3") + require.NotEqual(t, granterAddr, grantee3Addr) + grantee4Addr := cli.AddKey("grantee4") + require.NotEqual(t, granterAddr, grantee4Addr) + grantee5Addr := cli.AddKey("grantee5") + require.NotEqual(t, granterAddr, grantee5Addr) + grantee6Addr := cli.AddKey("grantee6") + require.NotEqual(t, granterAddr, grantee6Addr) + + sut.StartChain(t) + + // query validator operator address + rsp := cli.CustomQuery("q", "staking", "validators") + valOperAddr := gjson.Get(rsp, "validators.#.operator_address").Array()[0].String() + + grantCmdArgs := []string{"tx", "authz", "grant", "--from", granterAddr} + expirationTime := time.Now().Add(time.Hour).Unix() + + // test grant command + testCases := []struct { + name string + grantee string + cmdArgs []string + expErrMsg string + queryTx bool + }{ + { + "invalid authorization type", + grantee1Addr, + []string{"spend"}, + "invalid authorization type", + false, + }, + { + "send authorization without spend-limit", + grantee1Addr, + []string{"send"}, + "spend-limit should be greater than zero", + false, + }, + { + "generic authorization without msg type", + grantee1Addr, + []string{"generic"}, + "msg type cannot be empty", + true, + }, + { + "delegate authorization without allow or deny list", + grantee1Addr, + []string{"delegate"}, + "both allowed & deny list cannot be empty", + false, + }, + { + "delegate authorization with invalid allowed validator address", + grantee1Addr, + []string{"delegate", "--allowed-validators=invalid"}, + "decoding bech32 failed", + false, + }, + { + "delegate authorization with invalid deny validator address", + grantee1Addr, + []string{"delegate", "--deny-validators=invalid"}, + "decoding bech32 failed", + false, + }, + { + "unbond authorization without allow or deny list", + grantee1Addr, + []string{"unbond"}, + "both allowed & deny list cannot be empty", + false, + }, + { + "unbond authorization with invalid allowed validator address", + grantee1Addr, + []string{"unbond", "--allowed-validators=invalid"}, + "decoding bech32 failed", + false, + }, + { + "unbond authorization with invalid deny validator address", + grantee1Addr, + []string{"unbond", "--deny-validators=invalid"}, + "decoding bech32 failed", + false, + }, + { + "redelegate authorization without allow or deny list", + grantee1Addr, + []string{"redelegate"}, + "both allowed & deny list cannot be empty", + false, + }, + { + "redelegate authorization with invalid allowed validator address", + grantee1Addr, + []string{"redelegate", "--allowed-validators=invalid"}, + "decoding bech32 failed", + false, + }, + { + "redelegate authorization with invalid deny validator address", + grantee1Addr, + []string{"redelegate", "--deny-validators=invalid"}, + "decoding bech32 failed", + false, + }, + { + "valid send authorization", + grantee1Addr, + []string{"send", "--spend-limit=1000" + testDenom}, + "", + false, + }, + { + "valid send authorization with expiration", + grantee2Addr, + []string{"send", "--spend-limit=1000" + testDenom, fmt.Sprintf("--expiration=%d", expirationTime)}, + "", + false, + }, + { + "valid generic authorization", + grantee3Addr, + []string{"generic", "--msg-type=" + msgVoteTypeURL}, + "", + false, + }, + { + "valid delegate authorization", + grantee4Addr, + []string{"delegate", "--allowed-validators=" + valOperAddr}, + "", + false, + }, + { + "valid unbond authorization", + grantee5Addr, + []string{"unbond", "--deny-validators=" + valOperAddr}, + "", + false, + }, + { + "valid redelegate authorization", + grantee6Addr, + []string{"redelegate", "--allowed-validators=" + valOperAddr}, + "", + false, + }, + } + + grantsCount := 0 + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + cmd := append(append(grantCmdArgs, tc.grantee), tc.cmdArgs...) + if tc.expErrMsg != "" { + if tc.queryTx { + rsp := cli.Run(cmd...) + RequireTxFailure(t, rsp) + require.Contains(t, rsp, tc.expErrMsg) + } else { + assertErr := func(_ assert.TestingT, gotErr error, gotOutputs ...interface{}) bool { + require.Len(t, gotOutputs, 1) + output := gotOutputs[0].(string) + require.Contains(t, output, tc.expErrMsg) + return false + } + _ = cli.WithRunErrorMatcher(assertErr).Run(cmd...) + } + return + } + rsp := cli.RunAndWait(cmd...) + RequireTxSuccess(t, rsp) + + // query granter-grantee grants + resp := cli.CustomQuery("q", "authz", "grants", granterAddr, tc.grantee) + grants := gjson.Get(resp, "grants").Array() + // check grants length equal to 1 to confirm grant created successfully + require.Len(t, grants, 1) + grantsCount++ + }) + } + + // query grants-by-granter + resp := cli.CustomQuery("q", "authz", "grants-by-granter", granterAddr) + grants := gjson.Get(resp, "grants").Array() + require.Len(t, grants, grantsCount) +} + +func TestAuthzExecSendAuthorization(t *testing.T) { + // scenario: test authz exec send authorization + // given a running chain + + sut.ResetChain(t) + cli := NewCLIWrapper(t, sut, verbose) + + // get validator address which will be used as granter + granterAddr := cli.GetKeyAddr("node0") + require.NotEmpty(t, granterAddr) + + // add grantee keys which will be used for each valid transaction + granteeAddr := cli.AddKey("grantee") + require.NotEqual(t, granterAddr, granteeAddr) + allowedAddr := cli.AddKey("allowed") + require.NotEqual(t, granteeAddr, allowedAddr) + notAllowedAddr := cli.AddKey("notAllowed") + require.NotEqual(t, granteeAddr, notAllowedAddr) + newAccount := cli.AddKey("newAccount") + require.NotEqual(t, granteeAddr, newAccount) + + var initialAmount int64 = 10000000 + initialBalance := fmt.Sprintf("%d%s", initialAmount, testDenom) + sut.ModifyGenesisCLI(t, + []string{"genesis", "add-genesis-account", granteeAddr, initialBalance}, + []string{"genesis", "add-genesis-account", allowedAddr, initialBalance}, + []string{"genesis", "add-genesis-account", newAccount, initialBalance}, + ) + sut.StartChain(t) + + // query balances + granterBal := cli.QueryBalance(granterAddr, testDenom) + granteeBal := cli.QueryBalance(granteeAddr, testDenom) + require.Equal(t, initialAmount, granteeBal) + allowedAddrBal := cli.QueryBalance(allowedAddr, testDenom) + require.Equal(t, initialAmount, allowedAddrBal) + + var spendLimitAmount int64 = 1000 + expirationTime := time.Now().Add(time.Second * 10).Unix() + + // test exec send authorization + + // create send authorization grant + rsp := cli.RunAndWait("tx", "authz", "grant", granteeAddr, "send", + "--spend-limit="+fmt.Sprintf("%d%s", spendLimitAmount, testDenom), + "--allow-list="+allowedAddr, + "--expiration="+fmt.Sprintf("%d", expirationTime), + "--fees=1"+testDenom, + "--from", granterAddr) + RequireTxSuccess(t, rsp) + // reduce fees of above tx from granter balance + granterBal-- + + testCases := []struct { + name string + grantee string + toAddr string + amount int64 + expErrMsg string + }{ + { + "valid exec transaction", + granteeAddr, + allowedAddr, + 20, + "", + }, + { + "send to not allowed address", + granteeAddr, + notAllowedAddr, + 10, + "cannot send to", + }, + { + "amount greater than spend limit", + granteeAddr, + allowedAddr, + spendLimitAmount + 5, + "requested amount is more than spend limit", + }, + { + "no grant found", + newAccount, + granteeAddr, + 20, + "authorization not found", + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + // msg send + cmd := msgSendExec(t, granterAddr, tc.grantee, tc.toAddr, testDenom, tc.amount) + if tc.expErrMsg != "" { + rsp := cli.Run(cmd...) + RequireTxFailure(t, rsp) + require.Contains(t, rsp, tc.expErrMsg) + return + } + rsp := cli.RunAndWait(cmd...) + RequireTxSuccess(t, rsp) + + // check granter balance equals to granterBal - transferredAmount + expGranterBal := granterBal - tc.amount + require.Equal(t, expGranterBal, cli.QueryBalance(granterAddr, testDenom)) + granterBal = expGranterBal + + // check allowed addr balance equals to allowedAddrBal + transferredAmount + expAllowAddrBal := allowedAddrBal + tc.amount + require.Equal(t, expAllowAddrBal, cli.QueryBalance(allowedAddr, testDenom)) + allowedAddrBal = expAllowAddrBal + }) + } + + // test grant expiry + time.Sleep(time.Second * 10) + + execSendCmd := msgSendExec(t, granterAddr, granteeAddr, allowedAddr, testDenom, 10) + rsp = cli.Run(execSendCmd...) + RequireTxFailure(t, rsp) + require.Contains(t, rsp, "authorization not found") +} + +func TestAuthzExecGenericAuthorization(t *testing.T) { + // scenario: test authz exec generic authorization + // given a running chain + + cli, granterAddr, granteeAddr := setupChain(t) + + allowedAddr := cli.AddKey("allowedAddr") + require.NotEqual(t, granterAddr, allowedAddr) + + // query balances + granterBal := cli.QueryBalance(granterAddr, testDenom) + + expirationTime := time.Now().Add(time.Second * 5).Unix() + execSendCmd := msgSendExec(t, granterAddr, granteeAddr, allowedAddr, testDenom, 10) + + // create generic authorization grant + rsp := cli.RunAndWait("tx", "authz", "grant", granteeAddr, "generic", + "--msg-type="+msgSendTypeURL, + "--expiration="+fmt.Sprintf("%d", expirationTime), + "--fees=1"+testDenom, + "--from", granterAddr) + RequireTxSuccess(t, rsp) + granterBal-- + + rsp = cli.RunAndWait(execSendCmd...) + RequireTxSuccess(t, rsp) + // check granter balance equals to granterBal - transferredAmount + expGranterBal := granterBal - 10 + require.Equal(t, expGranterBal, cli.QueryBalance(granterAddr, testDenom)) + + time.Sleep(time.Second * 5) + + // check grants after expiration + resp := cli.CustomQuery("q", "authz", "grants", granterAddr, granteeAddr) + grants := gjson.Get(resp, "grants").Array() + require.Len(t, grants, 0) +} + +func TestAuthzExecDelegateAuthorization(t *testing.T) { + // scenario: test authz exec delegate authorization + // given a running chain + + cli, granterAddr, granteeAddr := setupChain(t) + + // query balances + granterBal := cli.QueryBalance(granterAddr, testDenom) + + // query validator operator address + rsp := cli.CustomQuery("q", "staking", "validators") + validators := gjson.Get(rsp, "validators.#.operator_address").Array() + require.GreaterOrEqual(t, len(validators), 2) + val1Addr := validators[0].String() + val2Addr := validators[1].String() + + var spendLimitAmount int64 = 1000 + require.Greater(t, granterBal, spendLimitAmount) + + rsp = cli.RunAndWait("tx", "authz", "grant", granteeAddr, "delegate", + "--spend-limit="+fmt.Sprintf("%d%s", spendLimitAmount, testDenom), + "--allowed-validators="+val1Addr, + "--fees=1"+testDenom, + "--from", granterAddr) + RequireTxSuccess(t, rsp) + // reduce fees of above tx from granter balance + granterBal-- + + delegateTestCases := []struct { + name string + grantee string + valAddr string + amount int64 + expErrMsg string + }{ + { + "valid txn: (delegate half tokens)", + granteeAddr, + val1Addr, + spendLimitAmount / 2, + "", + }, + { + "amount greater than spend limit", + granteeAddr, + val1Addr, + spendLimitAmount + 5, + "negative coin amount", + }, + { + "delegate to not allowed address", + granteeAddr, + val2Addr, + 10, + "cannot delegate", + }, + { + "valid txn: (delegate remaining half tokens)", + granteeAddr, + val1Addr, + spendLimitAmount / 2, + "", + }, + { + "no authorization found as grant prunes", + granteeAddr, + val1Addr, + spendLimitAmount / 2, + "authorization not found", + }, + } + + execCmdArgs := []string{"tx", "authz", "exec"} + + for _, tc := range delegateTestCases { + t.Run(tc.name, func(t *testing.T) { + delegateTx := fmt.Sprintf(`{"@type":"%s","delegator_address":"%s","validator_address":"%s","amount":{"denom":"%s","amount":"%d"}}`, + msgDelegateTypeURL, granterAddr, tc.valAddr, testDenom, tc.amount) + execMsg := WriteToTempJSONFile(t, delegateTx) + + cmd := append(append(execCmdArgs, execMsg.Name()), "--from="+tc.grantee) + if tc.expErrMsg != "" { + rsp := cli.Run(cmd...) + RequireTxFailure(t, rsp) + require.Contains(t, rsp, tc.expErrMsg) + return + } + rsp := cli.RunAndWait(cmd...) + RequireTxSuccess(t, rsp) + + // check granter balance equals to granterBal - transferredAmount + expGranterBal := granterBal - tc.amount + require.Equal(t, expGranterBal, cli.QueryBalance(granterAddr, testDenom)) + granterBal = expGranterBal + }) + } +} + +func TestAuthzExecUndelegateAuthorization(t *testing.T) { + // scenario: test authz exec undelegate authorization + // given a running chain + + cli, granterAddr, granteeAddr := setupChain(t) + + // query validator operator address + rsp := cli.CustomQuery("q", "staking", "validators") + validators := gjson.Get(rsp, "validators.#.operator_address").Array() + require.GreaterOrEqual(t, len(validators), 2) + val1Addr := validators[0].String() + val2Addr := validators[1].String() + + // delegate some tokens + rsp = cli.RunAndWait("tx", "staking", "delegate", val1Addr, "10000"+testDenom, "--from="+granterAddr) + RequireTxSuccess(t, rsp) + + // query delegated tokens count + resp := cli.CustomQuery("q", "staking", "delegation", granterAddr, val1Addr) + delegatedAmount := gjson.Get(resp, "delegation_response.balance.amount").Int() + + rsp = cli.RunAndWait("tx", "authz", "grant", granteeAddr, "unbond", + "--allowed-validators="+val1Addr, + "--fees=1"+testDenom, + "--from", granterAddr) + RequireTxSuccess(t, rsp) + + undelegateTestCases := []struct { + name string + grantee string + valAddr string + amount int64 + expErrMsg string + }{ + { + "valid transaction", + granteeAddr, + val1Addr, + 10, + "", + }, + { + "undelegate to not allowed address", + granteeAddr, + val2Addr, + 10, + "cannot delegate/undelegate", + }, + } + + for _, tc := range undelegateTestCases { + t.Run(tc.name, func(t *testing.T) { + undelegateTx := fmt.Sprintf(`{"@type":"%s","delegator_address":"%s","validator_address":"%s","amount":{"denom":"%s","amount":"%d"}}`, + msgUndelegateTypeURL, granterAddr, tc.valAddr, testDenom, tc.amount) + execMsg := WriteToTempJSONFile(t, undelegateTx) + + cmd := []string{"tx", "authz", "exec", execMsg.Name(), "--from=" + tc.grantee} + if tc.expErrMsg != "" { + rsp := cli.Run(cmd...) + RequireTxFailure(t, rsp) + require.Contains(t, rsp, tc.expErrMsg) + return + } + rsp := cli.RunAndWait(cmd...) + RequireTxSuccess(t, rsp) + + // query delegation and check balance reduced + expectedAmount := delegatedAmount - tc.amount + resp = cli.CustomQuery("q", "staking", "delegation", granterAddr, val1Addr) + delegatedAmount = gjson.Get(resp, "delegation_response.balance.amount").Int() + require.Equal(t, expectedAmount, delegatedAmount) + }) + } + + // revoke existing grant + rsp = cli.RunAndWait("tx", "authz", "revoke", granteeAddr, msgUndelegateTypeURL, "--from", granterAddr) + RequireTxSuccess(t, rsp) + + // check grants between granter and grantee after revoking + resp = cli.CustomQuery("q", "authz", "grants", granterAddr, granteeAddr) + grants := gjson.Get(resp, "grants").Array() + require.Len(t, grants, 0) +} + +func TestAuthzExecRedelegateAuthorization(t *testing.T) { + // scenario: test authz exec redelegate authorization + // given a running chain + + cli, granterAddr, granteeAddr := setupChain(t) + + // query validator operator address + rsp := cli.CustomQuery("q", "staking", "validators") + validators := gjson.Get(rsp, "validators.#.operator_address").Array() + require.GreaterOrEqual(t, len(validators), 2) + val1Addr := validators[0].String() + val2Addr := validators[1].String() + + // delegate some tokens + rsp = cli.RunAndWait("tx", "staking", "delegate", val1Addr, "10000"+testDenom, "--from="+granterAddr) + RequireTxSuccess(t, rsp) + + // test exec redelegate authorization + rsp = cli.RunAndWait("tx", "authz", "grant", granteeAddr, "redelegate", + fmt.Sprintf("--allowed-validators=%s,%s", val1Addr, val2Addr), + "--fees=1"+testDenom, + "--from", granterAddr) + RequireTxSuccess(t, rsp) + + var redelegationAmount int64 = 10 + + redelegateTx := fmt.Sprintf(`{"@type":"%s","delegator_address":"%s","validator_src_address":"%s","validator_dst_address":"%s","amount":{"denom":"%s","amount":"%d"}}`, + msgRedelegateTypeURL, granterAddr, val1Addr, val2Addr, testDenom, redelegationAmount) + execMsg := WriteToTempJSONFile(t, redelegateTx) + + redelegateCmd := []string{"tx", "authz", "exec", execMsg.Name(), "--from=" + granteeAddr, "--gas=auto"} + rsp = cli.RunAndWait(redelegateCmd...) + RequireTxSuccess(t, rsp) + + // query new delegation and check balance increased + resp := cli.CustomQuery("q", "staking", "delegation", granterAddr, val2Addr) + delegatedAmount := gjson.Get(resp, "delegation_response.balance.amount").Int() + require.GreaterOrEqual(t, delegatedAmount, redelegationAmount) + + // revoke all existing grants + rsp = cli.RunAndWait("tx", "authz", "revoke-all", "--from", granterAddr) + RequireTxSuccess(t, rsp) + + // check grants after revoking + resp = cli.CustomQuery("q", "authz", "grants-by-granter", granterAddr) + grants := gjson.Get(resp, "grants").Array() + require.Len(t, grants, 0) +} + +func TestAuthzGRPCQueries(t *testing.T) { + // scenario: test authz grpc gateway queries + // given a running chain + + cli, granterAddr, grantee1Addr := setupChain(t) + + grantee2Addr := cli.AddKey("grantee2") + require.NotEqual(t, granterAddr, grantee2Addr) + require.NotEqual(t, grantee1Addr, grantee2Addr) + + // create few grants + rsp := cli.RunAndWait("tx", "authz", "grant", grantee1Addr, "send", + "--spend-limit=10000"+testDenom, + "--from", granterAddr) + RequireTxSuccess(t, rsp) + grant1 := fmt.Sprintf(`"authorization":{"@type":"%s","spend_limit":[{"denom":"%s","amount":"10000"}],"allow_list":[]},"expiration":null`, sendAuthzTypeURL, testDenom) + + rsp = cli.RunAndWait("tx", "authz", "grant", grantee2Addr, "send", + "--spend-limit=1000"+testDenom, + "--from", granterAddr) + RequireTxSuccess(t, rsp) + grant2 := fmt.Sprintf(`"authorization":{"@type":"%s","spend_limit":[{"denom":"%s","amount":"1000"}],"allow_list":[]},"expiration":null`, sendAuthzTypeURL, testDenom) + + rsp = cli.RunAndWait("tx", "authz", "grant", grantee2Addr, "generic", + "--msg-type="+msgVoteTypeURL, + "--from", granterAddr) + RequireTxSuccess(t, rsp) + grant3 := fmt.Sprintf(`"authorization":{"@type":"%s","msg":"%s"},"expiration":null`, genericAuthzTypeURL, msgVoteTypeURL) + + rsp = cli.RunAndWait("tx", "authz", "grant", grantee2Addr, "generic", + "--msg-type="+msgDelegateTypeURL, + "--from", grantee1Addr) + RequireTxSuccess(t, rsp) + grant4 := fmt.Sprintf(`"authorization":{"@type":"%s","msg":"%s"},"expiration":null`, genericAuthzTypeURL, msgDelegateTypeURL) + + baseurl := sut.APIAddress() + + // test query grant grpc endpoint + grantURL := baseurl + "/cosmos/authz/v1beta1/grants?granter=%s&grantee=%s&msg_type_url=%s" + + bech32FailOutput := `{"code":2, "message":"decoding bech32 failed: invalid separator index -1", "details":[]}` + emptyStrOutput := `{"code":2, "message":"empty address string is not allowed", "details":[]}` + invalidMsgTypeOutput := `{"code":2, "message":"codespace authz code 2: authorization not found: authorization not found for invalidMsg type", "details":[]}` + expGrantOutput := fmt.Sprintf(`{"grants":[{%s}],"pagination":null}`, grant1) + + grantTestCases := []RestTestCase{ + { + "invalid granter address", + fmt.Sprintf(grantURL, "invalid_granter", grantee1Addr, msgSendTypeURL), + http.StatusInternalServerError, + bech32FailOutput, + }, + { + "invalid grantee address", + fmt.Sprintf(grantURL, granterAddr, "invalid_grantee", msgSendTypeURL), + http.StatusInternalServerError, + bech32FailOutput, + }, + { + "with empty granter", + fmt.Sprintf(grantURL, "", grantee1Addr, msgSendTypeURL), + http.StatusInternalServerError, + emptyStrOutput, + }, + { + "with empty grantee", + fmt.Sprintf(grantURL, granterAddr, "", msgSendTypeURL), + http.StatusInternalServerError, + emptyStrOutput, + }, + { + "invalid msg-type", + fmt.Sprintf(grantURL, granterAddr, grantee1Addr, "invalidMsg"), + http.StatusInternalServerError, + invalidMsgTypeOutput, + }, + { + "valid grant query", + fmt.Sprintf(grantURL, granterAddr, grantee1Addr, msgSendTypeURL), + http.StatusOK, + expGrantOutput, + }, + } + + RunRestQueries(t, grantTestCases) + + // test query grants grpc endpoint + grantsURL := baseurl + "/cosmos/authz/v1beta1/grants?granter=%s&grantee=%s" + + grantsTestCases := []RestTestCase{ + { + "expect single grant", + fmt.Sprintf(grantsURL, granterAddr, grantee1Addr), + http.StatusOK, + fmt.Sprintf(`{"grants":[{%s}],"pagination":{"next_key":null,"total":"1"}}`, grant1), + }, + { + "expect two grants", + fmt.Sprintf(grantsURL, granterAddr, grantee2Addr), + http.StatusOK, + fmt.Sprintf(`{"grants":[{%s},{%s}],"pagination":{"next_key":null,"total":"2"}}`, grant2, grant3), + }, + { + "expect single grant with pagination", + fmt.Sprintf(grantsURL+"&pagination.limit=1", granterAddr, grantee2Addr), + http.StatusOK, + fmt.Sprintf(`{"grants":[{%s}],"pagination":{"next_key":"L2Nvc21vcy5nb3YudjEuTXNnVm90ZQ==","total":"0"}}`, grant2), + }, + { + "expect single grant with pagination limit and offset", + fmt.Sprintf(grantsURL+"&pagination.limit=1&pagination.offset=1", granterAddr, grantee2Addr), + http.StatusOK, + fmt.Sprintf(`{"grants":[{%s}],"pagination":{"next_key":null,"total":"0"}}`, grant3), + }, + { + "expect two grants with pagination", + fmt.Sprintf(grantsURL+"&pagination.limit=2", granterAddr, grantee2Addr), + http.StatusOK, + fmt.Sprintf(`{"grants":[{%s},{%s}],"pagination":{"next_key":null,"total":"0"}}`, grant2, grant3), + }, + } + + RunRestQueries(t, grantsTestCases) + + // test query grants by granter grpc endpoint + grantsByGranterURL := baseurl + "/cosmos/authz/v1beta1/grants/granter/%s" + decodingFailedOutput := `{"code":2, "message":"decoding bech32 failed: invalid character in string: ' '", "details":[]}` + noAuthorizationsOutput := `{"grants":[],"pagination":{"next_key":null,"total":"0"}}` + granterQueryOutput := fmt.Sprintf(`{"grants":[{"granter":"%s","grantee":"%s",%s}],"pagination":{"next_key":null,"total":"1"}}`, + grantee1Addr, grantee2Addr, grant4) + + granterTestCases := []RestTestCase{ + { + "invalid granter account address", + fmt.Sprintf(grantsByGranterURL, "invalid address"), + http.StatusInternalServerError, + decodingFailedOutput, + }, + { + "no authorizations found from granter", + fmt.Sprintf(grantsByGranterURL, grantee2Addr), + http.StatusOK, + noAuthorizationsOutput, + }, + { + "valid granter query", + fmt.Sprintf(grantsByGranterURL, grantee1Addr), + http.StatusOK, + granterQueryOutput, + }, + } + + RunRestQueries(t, granterTestCases) + + // test query grants by grantee grpc endpoint + grantsByGranteeURL := baseurl + "/cosmos/authz/v1beta1/grants/grantee/%s" + grantee1GrantsOutput := fmt.Sprintf(`{"grants":[{"granter":"%s","grantee":"%s",%s}],"pagination":{"next_key":null,"total":"1"}}`, granterAddr, grantee1Addr, grant1) + + granteeTestCases := []RestTestCase{ + { + "invalid grantee account address", + fmt.Sprintf(grantsByGranteeURL, "invalid address"), + http.StatusInternalServerError, + decodingFailedOutput, + }, + { + "no authorizations found from grantee", + fmt.Sprintf(grantsByGranteeURL, granterAddr), + http.StatusOK, + noAuthorizationsOutput, + }, + { + "valid grantee query", + fmt.Sprintf(grantsByGranteeURL, grantee1Addr), + http.StatusOK, + grantee1GrantsOutput, + }, + } + + RunRestQueries(t, granteeTestCases) +} + +func setupChain(t *testing.T) (*CLIWrapper, string, string) { + t.Helper() + + sut.ResetChain(t) + cli := NewCLIWrapper(t, sut, verbose) + + require.GreaterOrEqual(t, cli.nodesCount, 2) + + // get validators' address which will be used as granter and grantee + granterAddr := cli.GetKeyAddr("node0") + require.NotEmpty(t, granterAddr) + granteeAddr := cli.GetKeyAddr("node1") + require.NotEmpty(t, granteeAddr) + + sut.StartChain(t) + + return cli, granterAddr, granteeAddr +} + +func msgSendExec(t *testing.T, granter, grantee, toAddr, denom string, amount int64) []string { + t.Helper() + + bankTx := fmt.Sprintf(`{ + "@type": "%s", + "from_address": "%s", + "to_address": "%s", + "amount": [ + { + "denom": "%s", + "amount": "%d" + } + ] + }`, msgSendTypeURL, granter, toAddr, denom, amount) + execMsg := WriteToTempJSONFile(t, bankTx) + + execSendCmd := []string{"tx", "authz", "exec", execMsg.Name(), "--from=" + grantee} + return execSendCmd +} + +// Write the given string to a new temporary json file. +// Returns an file for the test to use. +func WriteToTempJSONFile(tb testing.TB, s string) *os.File { + tb.Helper() + + tmpFile, err := os.CreateTemp(tb.TempDir(), "test-*.json") + require.NoError(tb, err) + + // Write to the temporary file + _, err = tmpFile.WriteString(s) + require.NoError(tb, err) + + // Close the file after writing + err = tmpFile.Close() + require.NoError(tb, err) + + return tmpFile +} diff --git a/tests/systemtests/bank_test.go b/tests/systemtests/bank_test.go index ae654fcba457..d776bc06a874 100644 --- a/tests/systemtests/bank_test.go +++ b/tests/systemtests/bank_test.go @@ -4,15 +4,13 @@ package systemtests import ( "fmt" + "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/tidwall/gjson" "github.com/tidwall/sjson" - - "github.com/cosmos/cosmos-sdk/testutil" - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" ) func TestBankSendTxCmd(t *testing.T) { @@ -23,7 +21,7 @@ func TestBankSendTxCmd(t *testing.T) { cli := NewCLIWrapper(t, sut, verbose) // get validator address - valAddr := gjson.Get(cli.Keys("keys", "list"), "1.address").String() + valAddr := cli.GetKeyAddr("node0") require.NotEmpty(t, valAddr) // add new key @@ -53,14 +51,14 @@ func TestBankSendTxCmd(t *testing.T) { insufficientCmdArgs = append(insufficientCmdArgs, fmt.Sprintf("%d%s", valBalance, denom), "--fees=10stake") rsp = cli.Run(insufficientCmdArgs...) RequireTxFailure(t, rsp) - require.Contains(t, rsp, sdkerrors.ErrInsufficientFunds.Error()) + require.Contains(t, rsp, "insufficient funds") // test tx bank send with unauthorized signature assertUnauthorizedErr := func(_ assert.TestingT, gotErr error, gotOutputs ...interface{}) bool { require.Len(t, gotOutputs, 1) code := gjson.Get(gotOutputs[0].(string), "code") require.True(t, code.Exists()) - require.Equal(t, int64(sdkerrors.ErrUnauthorized.ABCICode()), code.Int()) + require.Greater(t, code.Int(), int64(0)) return false } invalidCli := cli @@ -131,28 +129,24 @@ func TestBankMultiSendTxCmd(t *testing.T) { testCases := []struct { name string cmdArgs []string - expectErr bool expectedCode uint32 expErrMsg string }{ { "valid transaction", append(multiSendCmdArgs, "--fees=1stake"), - false, 0, "", }, { "not enough arguments", []string{"tx", "bank", "multi-send", account1Addr, account2Addr, "1000stake", "--from=" + account1Addr}, - true, 0, "only received 3", }, { "chain-id shouldn't be used with offline and generate-only flags", append(multiSendCmdArgs, "--generate-only", "--offline", "-a=0", "-s=4"), - true, 0, "chain ID cannot be used", }, @@ -160,7 +154,7 @@ func TestBankMultiSendTxCmd(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { - if tc.expectErr { + if tc.expErrMsg != "" { assertErr := func(_ assert.TestingT, gotErr error, gotOutputs ...interface{}) bool { require.Len(t, gotOutputs, 1) output := gotOutputs[0].(string) @@ -173,24 +167,24 @@ func TestBankMultiSendTxCmd(t *testing.T) { return false // always abort } _ = cli.WithRunErrorMatcher(assertErr).Run(tc.cmdArgs...) - } else { - rsp := cli.Run(tc.cmdArgs...) - txResult, found := cli.AwaitTxCommitted(rsp) - require.True(t, found) - RequireTxSuccess(t, txResult) - // check account1 balance equals to account1Bal - transferredAmount*no_of_accounts - fees - expAcc1Balance := account1Bal - (1000 * 2) - 1 - require.Equal(t, expAcc1Balance, cli.QueryBalance(account1Addr, denom)) - account1Bal = expAcc1Balance - // check account2 balance equals to account2Bal + transferredAmount - expAcc2Balance := account2Bal + 1000 - require.Equal(t, expAcc2Balance, cli.QueryBalance(account2Addr, denom)) - account2Bal = expAcc2Balance - // check account3 balance equals to account3Bal + transferredAmount - expAcc3Balance := account3Bal + 1000 - require.Equal(t, expAcc3Balance, cli.QueryBalance(account3Addr, denom)) - account3Bal = expAcc3Balance + return } + rsp := cli.Run(tc.cmdArgs...) + txResult, found := cli.AwaitTxCommitted(rsp) + require.True(t, found) + RequireTxSuccess(t, txResult) + // check account1 balance equals to account1Bal - transferredAmount*no_of_accounts - fees + expAcc1Balance := account1Bal - (1000 * 2) - 1 + require.Equal(t, expAcc1Balance, cli.QueryBalance(account1Addr, denom)) + account1Bal = expAcc1Balance + // check account2 balance equals to account2Bal + transferredAmount + expAcc2Balance := account2Bal + 1000 + require.Equal(t, expAcc2Balance, cli.QueryBalance(account2Addr, denom)) + account2Bal = expAcc2Balance + // check account3 balance equals to account3Bal + transferredAmount + expAcc3Balance := account3Bal + 1000 + require.Equal(t, expAcc3Balance, cli.QueryBalance(account3Addr, denom)) + account3Bal = expAcc3Balance }) } } @@ -224,7 +218,7 @@ func TestBankGRPCQueries(t *testing.T) { // start chain sut.StartChain(t) - baseurl := fmt.Sprintf("http://localhost:%d", apiPortStart) + baseurl := sut.APIAddress() // test supply grpc endpoint supplyUrl := baseurl + "/cosmos/bank/v1beta1/supply" @@ -238,10 +232,11 @@ func TestBankGRPCQueries(t *testing.T) { blockHeight := sut.CurrentHeight() supplyTestCases := []struct { - name string - url string - headers map[string]string - expOut string + name string + url string + headers map[string]string + expHttpCode int + expOut string }{ { "test GRPC total supply", @@ -249,12 +244,14 @@ func TestBankGRPCQueries(t *testing.T) { map[string]string{ blockHeightHeader: fmt.Sprintf("%d", blockHeight), }, + http.StatusOK, expTotalSupplyOutput, }, { "test GRPC total supply of a specific denom", supplyUrl + "/by_denom?denom=" + newDenom, map[string]string{}, + http.StatusOK, specificDenomOutput, }, { @@ -263,87 +260,75 @@ func TestBankGRPCQueries(t *testing.T) { map[string]string{ blockHeightHeader: fmt.Sprintf("%d", blockHeight+5), }, + http.StatusInternalServerError, "invalid height", }, { "test GRPC total supply of a bogus denom", supplyUrl + "/by_denom?denom=foobar", map[string]string{}, + http.StatusOK, + // http.StatusNotFound, bogusDenomOutput, }, } for _, tc := range supplyTestCases { t.Run(tc.name, func(t *testing.T) { - resp, err := testutil.GetRequestWithHeaders(tc.url, tc.headers) - require.NoError(t, err) + resp := GetRequestWithHeaders(t, tc.url, tc.headers, tc.expHttpCode) require.Contains(t, string(resp), tc.expOut) }) } // test denom metadata endpoint denomMetadataUrl := baseurl + "/cosmos/bank/v1beta1/denoms_metadata" - dmTestCases := []struct { - name string - url string - expOut string - }{ + dmTestCases := []RestTestCase{ { "test GRPC client metadata", denomMetadataUrl, - bankDenomMetadata, + http.StatusOK, + fmt.Sprintf(`{"metadatas":%s,"pagination":{"next_key":null,"total":"2"}}`, bankDenomMetadata), }, { "test GRPC client metadata of a specific denom", denomMetadataUrl + "/uatom", - atomDenomMetadata, + http.StatusOK, + fmt.Sprintf(`{"metadata":%s}`, atomDenomMetadata), }, { "test GRPC client metadata of a bogus denom", denomMetadataUrl + "/foobar", - `"details":[]`, + http.StatusNotFound, + `{"code":5, "message":"client metadata for denom foobar", "details":[]}`, }, } - for _, tc := range dmTestCases { - t.Run(tc.name, func(t *testing.T) { - resp, err := testutil.GetRequest(tc.url) - require.NoError(t, err) - require.Contains(t, string(resp), tc.expOut) - }) - } + RunRestQueries(t, dmTestCases) // test bank balances endpoint balanceUrl := baseurl + "/cosmos/bank/v1beta1/balances/" allBalancesOutput := `{"balances":[` + specificDenomOutput + `,{"denom":"stake","amount":"10000000"}],"pagination":{"next_key":null,"total":"2"}}` - balanceTestCases := []struct { - name string - url string - expOut string - }{ + balanceTestCases := []RestTestCase{ { "test GRPC total account balance", balanceUrl + account1Addr, + http.StatusOK, allBalancesOutput, }, { "test GRPC account balance of a specific denom", fmt.Sprintf("%s%s/by_denom?denom=%s", balanceUrl, account1Addr, newDenom), - specificDenomOutput, + http.StatusOK, + fmt.Sprintf(`{"balance":%s}`, specificDenomOutput), }, { "test GRPC account balance of a bogus denom", fmt.Sprintf("%s%s/by_denom?denom=foobar", balanceUrl, account1Addr), - bogusDenomOutput, + http.StatusOK, + fmt.Sprintf(`{"balance":%s}`, bogusDenomOutput), }, } - for _, tc := range balanceTestCases { - t.Run(tc.name, func(t *testing.T) { - resp, err := testutil.GetRequest(tc.url) - require.NoError(t, err) - require.Contains(t, string(resp), tc.expOut) - }) - } + RunRestQueries(t, balanceTestCases) } diff --git a/tests/systemtests/bankv2_test.go b/tests/systemtests/bankv2_test.go new file mode 100644 index 000000000000..b753ee0be430 --- /dev/null +++ b/tests/systemtests/bankv2_test.go @@ -0,0 +1,58 @@ +//go:build system_test + +package systemtests + +import ( + "fmt" + "testing" + + "github.com/stretchr/testify/require" + "github.com/tidwall/gjson" +) + +func TestBankV2SendTxCmd(t *testing.T) { + // Currently only run with app v2 + if !isV2() { + t.Skip() + } + // scenario: test bank send command + // given a running chain + + sut.ResetChain(t) + cli := NewCLIWrapper(t, sut, verbose) + + // get validator address + valAddr := gjson.Get(cli.Keys("keys", "list"), "1.address").String() + require.NotEmpty(t, valAddr) + + // add new key + receiverAddr := cli.AddKey("account1") + denom := "stake" + sut.StartChain(t) + + // query validator balance and make sure it has enough balance + var transferAmount int64 = 1000 + raw := cli.CustomQuery("q", "bankv2", "balance", valAddr, denom) + valBalance := gjson.Get(raw, "balance.amount").Int() + + require.Greater(t, valBalance, transferAmount, "not enough balance found with validator") + + bankSendCmdArgs := []string{"tx", "bankv2", "send", valAddr, receiverAddr, fmt.Sprintf("%d%s", transferAmount, denom)} + + // test valid transaction + rsp := cli.Run(append(bankSendCmdArgs, "--fees=1stake")...) + txResult, found := cli.AwaitTxCommitted(rsp) + require.True(t, found) + RequireTxSuccess(t, txResult) + + // Check balance after send + valRaw := cli.CustomQuery("q", "bankv2", "balance", valAddr, denom) + valBalanceAfer := gjson.Get(valRaw, "balance.amount").Int() + + // TODO: Make DeductFee ante handler work with bank/v2 + require.Equal(t, valBalanceAfer, valBalance-transferAmount) + + receiverRaw := cli.CustomQuery("q", "bankv2", "balance", receiverAddr, denom) + receiverBalance := gjson.Get(receiverRaw, "balance.amount").Int() + require.Equal(t, receiverBalance, transferAmount) +} diff --git a/tests/systemtests/cli.go b/tests/systemtests/cli.go index fcc6bb518c05..d7ac2368ae79 100644 --- a/tests/systemtests/cli.go +++ b/tests/systemtests/cli.go @@ -179,6 +179,13 @@ func (c CLIWrapper) RunAndWait(args ...string) string { return txResult } +// RunCommandWithArgs use for run cli command, not tx +func (c CLIWrapper) RunCommandWithArgs(args ...string) string { + c.t.Helper() + execOutput, _ := c.run(args) + return execOutput +} + // AwaitTxCommitted wait for tx committed on chain // returns the server execution result and true when found within 3 blocks. func (c CLIWrapper) AwaitTxCommitted(submitResp string, timeout ...time.Duration) (string, bool) { diff --git a/tests/systemtests/cometbft_client_test.go b/tests/systemtests/cometbft_client_test.go new file mode 100644 index 000000000000..0c9fd62bb5bd --- /dev/null +++ b/tests/systemtests/cometbft_client_test.go @@ -0,0 +1,325 @@ +//go:build system_test + +package systemtests + +import ( + "context" + "fmt" + "net/url" + "testing" + "time" + + "github.com/stretchr/testify/assert" + "github.com/tidwall/gjson" + + "github.com/cosmos/cosmos-sdk/client/grpc/cmtservice" + "github.com/cosmos/cosmos-sdk/codec" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" + qtypes "github.com/cosmos/cosmos-sdk/types/query" +) + +func TestQueryNodeInfo(t *testing.T) { + baseurl := fmt.Sprintf("http://localhost:%d", apiPortStart) + sut.ResetChain(t) + sut.StartChain(t) + + qc := cmtservice.NewServiceClient(sut.RPCClient(t)) + res, err := qc.GetNodeInfo(context.Background(), &cmtservice.GetNodeInfoRequest{}) + assert.NoError(t, err) + + v := NewCLIWrapper(t, sut, true).Version() + assert.Equal(t, res.ApplicationVersion.Version, v) + + // TODO: we should be adding a way to distinguish a v2. Eventually we should skip some v2 system depending on the consensus engine we want to test + restRes := GetRequest(t, mustV(url.JoinPath(baseurl, "/cosmos/base/tendermint/v1beta1/node_info"))) + assert.NoError(t, err) + assert.Equal(t, gjson.GetBytes(restRes, "application_version.version").String(), res.ApplicationVersion.Version) +} + +func TestQuerySyncing(t *testing.T) { + baseurl := fmt.Sprintf("http://localhost:%d", apiPortStart) + sut.ResetChain(t) + sut.StartChain(t) + + qc := cmtservice.NewServiceClient(sut.RPCClient(t)) + res, err := qc.GetSyncing(context.Background(), &cmtservice.GetSyncingRequest{}) + assert.NoError(t, err) + + restRes := GetRequest(t, mustV(url.JoinPath(baseurl, "/cosmos/base/tendermint/v1beta1/syncing"))) + assert.Equal(t, gjson.GetBytes(restRes, "syncing").Bool(), res.Syncing) +} + +func TestQueryLatestBlock(t *testing.T) { + baseurl := fmt.Sprintf("http://localhost:%d", apiPortStart) + sut.ResetChain(t) + sut.StartChain(t) + + qc := cmtservice.NewServiceClient(sut.RPCClient(t)) + res, err := qc.GetLatestBlock(context.Background(), &cmtservice.GetLatestBlockRequest{}) + assert.NoError(t, err) + assert.Contains(t, res.SdkBlock.Header.ProposerAddress, "cosmosvalcons") + + _ = GetRequest(t, mustV(url.JoinPath(baseurl, "/cosmos/base/tendermint/v1beta1/blocks/latest"))) +} + +func TestQueryBlockByHeight(t *testing.T) { + baseurl := fmt.Sprintf("http://localhost:%d", apiPortStart) + sut.ResetChain(t) + sut.StartChain(t) + + sut.AwaitNBlocks(t, 2, time.Second*25) + + qc := cmtservice.NewServiceClient(sut.RPCClient(t)) + res, err := qc.GetBlockByHeight(context.Background(), &cmtservice.GetBlockByHeightRequest{Height: 2}) + assert.NoError(t, err) + assert.Equal(t, res.SdkBlock.Header.Height, int64(2)) + assert.Contains(t, res.SdkBlock.Header.ProposerAddress, "cosmosvalcons") + + restRes := GetRequest(t, mustV(url.JoinPath(baseurl, "/cosmos/base/tendermint/v1beta1/blocks/2"))) + assert.Equal(t, gjson.GetBytes(restRes, "sdk_block.header.height").Int(), int64(2)) + assert.Contains(t, gjson.GetBytes(restRes, "sdk_block.header.proposer_address").String(), "cosmosvalcons") +} + +func TestQueryLatestValidatorSet(t *testing.T) { + baseurl := fmt.Sprintf("http://localhost:%d", apiPortStart) + sut.ResetChain(t) + sut.StartChain(t) + + vals := sut.RPCClient(t).Validators() + + qc := cmtservice.NewServiceClient(sut.RPCClient(t)) + res, err := qc.GetLatestValidatorSet(context.Background(), &cmtservice.GetLatestValidatorSetRequest{ + Pagination: nil, + }) + assert.NoError(t, err) + assert.Equal(t, len(res.Validators), len(vals)) + + // with pagination + res, err = qc.GetLatestValidatorSet(context.Background(), &cmtservice.GetLatestValidatorSetRequest{Pagination: &qtypes.PageRequest{ + Offset: 0, + Limit: 2, + }}) + assert.NoError(t, err) + assert.Equal(t, len(res.Validators), 2) + + restRes := GetRequest(t, mustV(url.JoinPath(baseurl, "/cosmos/base/tendermint/v1beta1/validatorsets/latest?pagination.offset=0&pagination.limit=2"))) + assert.Equal(t, len(gjson.GetBytes(restRes, "validators").Array()), 2) +} + +func TestLatestValidatorSet(t *testing.T) { + sut.ResetChain(t) + sut.StartChain(t) + + vals := sut.RPCClient(t).Validators() + + qc := cmtservice.NewServiceClient(sut.RPCClient(t)) + testCases := []struct { + name string + req *cmtservice.GetLatestValidatorSetRequest + expErr bool + expErrMsg string + }{ + {"nil request", nil, true, "cannot be nil"}, + {"no pagination", &cmtservice.GetLatestValidatorSetRequest{}, false, ""}, + {"with pagination", &cmtservice.GetLatestValidatorSetRequest{Pagination: &qtypes.PageRequest{Offset: 0, Limit: uint64(len(vals))}}, false, ""}, + } + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + res, err := qc.GetLatestValidatorSet(context.Background(), tc.req) + if tc.expErr { + assert.Error(t, err) + assert.Contains(t, err.Error(), tc.expErrMsg) + } else { + assert.NoError(t, err) + assert.Equal(t, len(res.Validators), len(vals)) + content, ok := res.Validators[0].PubKey.GetCachedValue().(cryptotypes.PubKey) + assert.True(t, ok) + assert.Equal(t, content.Address(), vals[0].PubKey.Address()) + } + }) + } +} + +func TestLatestValidatorSet_GRPCGateway(t *testing.T) { + sut.ResetChain(t) + sut.StartChain(t) + + baseurl := fmt.Sprintf("http://localhost:%d", apiPortStart) + + vals := sut.RPCClient(t).Validators() + + testCases := []struct { + name string + url string + expErr bool + expErrMsg string + }{ + {"no pagination", "/cosmos/base/tendermint/v1beta1/validatorsets/latest", false, ""}, + {"pagination invalid fields", "/cosmos/base/tendermint/v1beta1/validatorsets/latest?pagination.offset=-1&pagination.limit=-2", true, "strconv.ParseUint"}, + {"with pagination", "/cosmos/base/tendermint/v1beta1/validatorsets/latest?pagination.offset=0&pagination.limit=2", false, ""}, + } + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + rsp := GetRequest(t, mustV(url.JoinPath(baseurl, tc.url))) + if tc.expErr { + errMsg := gjson.GetBytes(rsp, "message").String() + assert.Contains(t, errMsg, tc.expErrMsg) + } else { + assert.Equal(t, len(vals), int(gjson.GetBytes(rsp, "pagination.total").Int())) + } + }) + } +} + +func TestValidatorSetByHeight(t *testing.T) { + sut.ResetChain(t) + sut.StartChain(t) + + qc := cmtservice.NewServiceClient(sut.RPCClient(t)) + vals := sut.RPCClient(t).Validators() + + testCases := []struct { + name string + req *cmtservice.GetValidatorSetByHeightRequest + expErr bool + expErrMsg string + }{ + {"nil request", nil, true, "request cannot be nil"}, + {"empty request", &cmtservice.GetValidatorSetByHeightRequest{}, true, "height must be greater than 0"}, + {"no pagination", &cmtservice.GetValidatorSetByHeightRequest{Height: 1}, false, ""}, + {"with pagination", &cmtservice.GetValidatorSetByHeightRequest{Height: 1, Pagination: &qtypes.PageRequest{Offset: 0, Limit: uint64(len(vals))}}, false, ""}, + } + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + res, err := qc.GetValidatorSetByHeight(context.Background(), tc.req) + if tc.expErr { + assert.Error(t, err) + assert.Contains(t, err.Error(), tc.expErrMsg) + } else { + assert.NoError(t, err) + assert.Equal(t, len(res.Validators), len(vals)) + } + }) + } +} + +func TestValidatorSetByHeight_GRPCGateway(t *testing.T) { + sut.ResetChain(t) + sut.StartChain(t) + + vals := sut.RPCClient(t).Validators() + + baseurl := fmt.Sprintf("http://localhost:%d", apiPortStart) + + block := sut.AwaitNextBlock(t, time.Second*3) + testCases := []struct { + name string + url string + expErr bool + expErrMsg string + }{ + {"invalid height", fmt.Sprintf("%s/cosmos/base/tendermint/v1beta1/validatorsets/%d", baseurl, -1), true, "height must be greater than 0"}, + {"no pagination", fmt.Sprintf("%s/cosmos/base/tendermint/v1beta1/validatorsets/%d", baseurl, block), false, ""}, + {"pagination invalid fields", fmt.Sprintf("%s/cosmos/base/tendermint/v1beta1/validatorsets/%d?pagination.offset=-1&pagination.limit=-2", baseurl, block), true, "strconv.ParseUint"}, + {"with pagination", fmt.Sprintf("%s/cosmos/base/tendermint/v1beta1/validatorsets/%d?pagination.limit=2", baseurl, 1), false, ""}, + } + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + rsp := GetRequest(t, tc.url) + if tc.expErr { + errMsg := gjson.GetBytes(rsp, "message").String() + assert.Contains(t, errMsg, tc.expErrMsg) + } else { + assert.Equal(t, len(vals), int(gjson.GetBytes(rsp, "pagination.total").Int())) + } + }) + } +} + +func TestABCIQuery(t *testing.T) { + sut.ResetChain(t) + sut.StartChain(t) + + qc := cmtservice.NewServiceClient(sut.RPCClient(t)) + cdc := codec.NewProtoCodec(codectypes.NewInterfaceRegistry()) + testCases := []struct { + name string + req *cmtservice.ABCIQueryRequest + expectErr bool + expectedCode uint32 + validQuery bool + }{ + { + name: "valid request with proof", + req: &cmtservice.ABCIQueryRequest{ + Path: "/store/gov/key", + Data: []byte{0x03}, + Prove: true, + }, + validQuery: true, + }, + { + name: "valid request without proof", + req: &cmtservice.ABCIQueryRequest{ + Path: "/store/gov/key", + Data: []byte{0x03}, + Prove: false, + }, + validQuery: true, + }, + { + name: "request with invalid path", + req: &cmtservice.ABCIQueryRequest{ + Path: "/foo/bar", + Data: []byte{0x03}, + }, + expectErr: true, + }, + { + name: "request with invalid path recursive", + req: &cmtservice.ABCIQueryRequest{ + Path: "/cosmos.base.tendermint.v1beta1.Service/ABCIQuery", + Data: cdc.MustMarshal(&cmtservice.ABCIQueryRequest{ + Path: "/cosmos.base.tendermint.v1beta1.Service/ABCIQuery", + }), + }, + expectErr: true, + }, + { + name: "request with invalid broadcast tx path", + req: &cmtservice.ABCIQueryRequest{ + Path: "/cosmos.tx.v1beta1.Service/BroadcastTx", + Data: []byte{0x00}, + }, + expectErr: true, + }, + { + name: "request with invalid data", + req: &cmtservice.ABCIQueryRequest{ + Path: "/store/gov/key", + Data: []byte{0x0044, 0x00}, + }, + validQuery: false, + }, + } + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + res, err := qc.ABCIQuery(context.Background(), tc.req) + if tc.expectErr { + assert.Error(t, err) + assert.Nil(t, res) + } else { + assert.NoError(t, err) + assert.NotNil(t, res) + assert.Equal(t, res.Code, tc.expectedCode) + } + + if tc.validQuery { + assert.Greater(t, res.Height, int64(0)) + assert.Greater(t, len(res.Key), 0) + assert.Greater(t, len(res.Value), 0) + } + }) + } +} diff --git a/tests/systemtests/fraud_test.go b/tests/systemtests/fraud_test.go index a383669eeff6..0479f526cc2d 100644 --- a/tests/systemtests/fraud_test.go +++ b/tests/systemtests/fraud_test.go @@ -11,8 +11,6 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/tidwall/gjson" - - cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" ) func TestValidatorDoubleSign(t *testing.T) { @@ -27,43 +25,37 @@ func TestValidatorDoubleSign(t *testing.T) { // Check the validator is in the active set rsp := cli.CustomQuery("q", "staking", "validators") t.Log(rsp) - nodePowerBefore := QueryCometValidatorPowerForNode(t, sut, 0) + validatorPubKey := LoadValidatorPubKeyForNode(t, sut, 0) + rpc, pkBz := sut.RPCClient(t), validatorPubKey.Bytes() + + nodePowerBefore := QueryCometValidatorPower(rpc, pkBz) require.NotEmpty(t, nodePowerBefore) t.Logf("nodePowerBefore: %v", nodePowerBefore) - var validatorPubKey cryptotypes.PubKey newNode := sut.AddFullnode(t, func(nodeNumber int, nodePath string) { valKeyFile := filepath.Join(WorkDir, nodePath, "config", "priv_validator_key.json") _ = os.Remove(valKeyFile) - _, err := copyFile(filepath.Join(WorkDir, sut.nodePath(0), "config", "priv_validator_key.json"), valKeyFile) - require.NoError(t, err) - validatorPubKey = LoadValidatorPubKeyForNode(t, sut, nodeNumber) + _ = MustCopyFile(filepath.Join(WorkDir, sut.nodePath(0), "config", "priv_validator_key.json"), valKeyFile) }) sut.AwaitNodeUp(t, fmt.Sprintf("http://%s:%d", newNode.IP, newNode.RPCPort)) // let's wait some blocks to have evidence and update persisted - rpc := sut.RPCClient(t) - pkBz := validatorPubKey.Bytes() - for i := 0; i < 20; i++ { + var nodePowerAfter int64 = -1 + for i := 0; i < 30; i++ { sut.AwaitNextBlock(t) - if QueryCometValidatorPower(rpc, pkBz) == 0 { + if nodePowerAfter = QueryCometValidatorPower(rpc, pkBz); nodePowerAfter == 0 { break } + t.Logf("wait %d", sut.CurrentHeight()) } - sut.AwaitNextBlock(t) - // then comet status updated - nodePowerAfter := QueryCometValidatorPowerForNode(t, sut, 0) require.Empty(t, nodePowerAfter) - t.Logf("nodePowerAfter: %v", nodePowerAfter) // and sdk status updated byzantineOperatorAddr := cli.GetKeyAddrPrefix("node0", "val") rsp = cli.CustomQuery("q", "staking", "validator", byzantineOperatorAddr) assert.True(t, gjson.Get(rsp, "validator.jailed").Bool(), rsp) - t.Log("let's run for some blocks to confirm all good") - for i := 0; i < 10; i++ { - sut.AwaitNextBlock(t) - } + // let's run for some blocks to confirm all good + sut.AwaitNBlocks(t, 5) } diff --git a/tests/systemtests/getting_started.md b/tests/systemtests/getting_started.md index 47bee4dafa5f..7adc98f1b3e9 100644 --- a/tests/systemtests/getting_started.md +++ b/tests/systemtests/getting_started.md @@ -182,7 +182,7 @@ go test -mod=readonly -tags='system_test' -v ./... --run TestQueryTotalSupply - ## Part 4: Set state via TX Complexer workflows and tests require modifying state on a running chain. This works only with builtin logic and operations. -If we want to burn some our new tokens, we need to submit a bank burn message to do this. +If we want to burn some of our new tokens, we need to submit a bank burn message to do this. The CLI wrapper works similar to the query. Just pass the parameters. It uses the `node0` key as *default*: ```go diff --git a/tests/systemtests/go.mod b/tests/systemtests/go.mod index 0ab29370379e..6203d6d05d05 100644 --- a/tests/systemtests/go.mod +++ b/tests/systemtests/go.mod @@ -13,26 +13,27 @@ require ( github.com/gorilla/mux v1.8.0 // indirect github.com/grpc-ecosystem/grpc-gateway v1.16.0 // indirect github.com/pkg/errors v0.9.1 // indirect - github.com/prometheus/client_golang v1.20.3 // indirect + github.com/prometheus/client_golang v1.20.4 // indirect github.com/spf13/cast v1.7.0 // indirect github.com/spf13/cobra v1.8.1 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/stretchr/testify v1.9.0 github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d // indirect google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de // indirect - google.golang.org/grpc v1.66.2 // indirect + google.golang.org/grpc v1.67.1 ) require ( cosmossdk.io/math v1.3.0 github.com/cometbft/cometbft v0.38.8 + github.com/cometbft/cometbft/api v1.0.0-rc.1 github.com/creachadair/tomledit v0.0.26 github.com/tidwall/gjson v1.14.2 github.com/tidwall/sjson v1.2.5 ) require ( - cosmossdk.io/api v0.7.5 // indirect + cosmossdk.io/api v0.7.6 // indirect cosmossdk.io/collections v0.4.0 // indirect cosmossdk.io/core v0.11.0 // indirect cosmossdk.io/depinject v1.0.0 // indirect @@ -81,7 +82,7 @@ require ( github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect github.com/gogo/googleapis v1.4.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang/glog v1.2.1 // indirect + github.com/golang/glog v1.2.2 // indirect github.com/golang/snappy v0.0.4 // indirect github.com/google/btree v1.1.2 // indirect github.com/google/go-cmp v0.6.0 // indirect @@ -99,7 +100,7 @@ require ( github.com/hashicorp/hcl v1.0.0 // indirect github.com/hashicorp/yamux v0.1.1 // indirect github.com/hdevalence/ed25519consensus v0.1.0 // indirect - github.com/huandu/skiplist v1.2.0 // indirect + github.com/huandu/skiplist v1.2.1 // indirect github.com/iancoleman/strcase v0.3.0 // indirect github.com/improbable-eng/grpc-web v0.15.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect @@ -124,7 +125,7 @@ require ( github.com/petermattis/goid v0.0.0-20231207134359-e60b3f734c67 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/prometheus/client_model v0.6.1 // indirect - github.com/prometheus/common v0.59.1 // indirect + github.com/prometheus/common v0.60.0 // indirect github.com/prometheus/procfs v0.15.1 // indirect github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect github.com/rogpeppe/go-internal v1.12.0 // indirect @@ -152,8 +153,8 @@ require ( golang.org/x/sys v0.25.0 // indirect golang.org/x/term v0.24.0 // indirect golang.org/x/text v0.18.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f // indirect google.golang.org/protobuf v1.34.2 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/tests/systemtests/go.sum b/tests/systemtests/go.sum index c3c0ea61cb06..746009230523 100644 --- a/tests/systemtests/go.sum +++ b/tests/systemtests/go.sum @@ -1,7 +1,7 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cosmossdk.io/api v0.7.5 h1:eMPTReoNmGUm8DeiQL9DyM8sYDjEhWzL1+nLbI9DqtQ= -cosmossdk.io/api v0.7.5/go.mod h1:IcxpYS5fMemZGqyYtErK7OqvdM0C8kdW3dq8Q/XIG38= +cosmossdk.io/api v0.7.6 h1:PC20PcXy1xYKH2KU4RMurVoFjjKkCgYRbVAD4PdqUuY= +cosmossdk.io/api v0.7.6/go.mod h1:IcxpYS5fMemZGqyYtErK7OqvdM0C8kdW3dq8Q/XIG38= cosmossdk.io/collections v0.4.0 h1:PFmwj2W8szgpD5nOd8GWH6AbYNi1f2J6akWXJ7P5t9s= cosmossdk.io/collections v0.4.0/go.mod h1:oa5lUING2dP+gdDquow+QjlF45eL1t4TJDypgGd+tv0= cosmossdk.io/core v0.11.0 h1:vtIafqUi+1ZNAE/oxLOQQ7Oek2n4S48SWLG8h/+wdbo= @@ -129,6 +129,8 @@ github.com/cometbft/cometbft v0.38.8 h1:XyJ9Cu3xqap6xtNxiemrO8roXZ+KS2Zlu7qQ0w1t github.com/cometbft/cometbft v0.38.8/go.mod h1:xOoGZrtUT+A5izWfHSJgl0gYZUE7lu7Z2XIS1vWG/QQ= github.com/cometbft/cometbft-db v0.9.1 h1:MIhVX5ja5bXNHF8EYrThkG9F7r9kSfv8BX4LWaxWJ4M= github.com/cometbft/cometbft-db v0.9.1/go.mod h1:iliyWaoV0mRwBJoizElCwwRA9Tf7jZJOURcRZF9m60U= +github.com/cometbft/cometbft/api v1.0.0-rc.1 h1:GtdXwDGlqwHYs16A4egjwylfYOMYyEacLBrs3Zvpt7g= +github.com/cometbft/cometbft/api v1.0.0-rc.1/go.mod h1:NDFKiBBD8HJC6QQLAoUI99YhsiRZtg2+FJWfk6A6m6o= github.com/containerd/continuity v0.3.0 h1:nisirsYROK15TAMVukJOUyGJjz4BNQJBVsNvAXZJ/eg= github.com/containerd/continuity v0.3.0/go.mod h1:wJEAIwKOm/pBZuBd0JmeTvnLquTB1Ag8espWhkykbPM= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= @@ -287,8 +289,8 @@ github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXP github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/glog v1.2.1 h1:OptwRhECazUx5ix5TTWC3EZhsZEHWcYWY4FQHTIubm4= -github.com/golang/glog v1.2.1/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= +github.com/golang/glog v1.2.2 h1:1+mZ9upx1Dh6FmUTFR1naJ77miKiXgALjWOZ3NVFPmY= +github.com/golang/glog v1.2.2/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= @@ -406,8 +408,8 @@ github.com/hdevalence/ed25519consensus v0.1.0/go.mod h1:w3BHWjwJbFU29IRHL1Iqkw3s github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/huandu/go-assert v1.1.5 h1:fjemmA7sSfYHJD7CUqs9qTwwfdNAx7/j2/ZlHXzNB3c= github.com/huandu/go-assert v1.1.5/go.mod h1:yOLvuqZwmcHIC5rIzrBhT7D3Q9c3GFnd0JrPVhn/06U= -github.com/huandu/skiplist v1.2.0 h1:gox56QD77HzSC0w+Ws3MH3iie755GBJU1OER3h5VsYw= -github.com/huandu/skiplist v1.2.0/go.mod h1:7v3iFjLcSAzO4fN5B8dvebvo/qsfumiLiDXMrPiHF9w= +github.com/huandu/skiplist v1.2.1 h1:dTi93MgjwErA/8idWTzIw4Y1kZsMWx35fmI2c8Rij7w= +github.com/huandu/skiplist v1.2.1/go.mod h1:7v3iFjLcSAzO4fN5B8dvebvo/qsfumiLiDXMrPiHF9w= github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI= github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= @@ -599,8 +601,8 @@ 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.20.3 h1:oPksm4K8B+Vt35tUhw6GbSNSgVlVSBH0qELP/7u83l4= -github.com/prometheus/client_golang v1.20.3/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_golang v1.20.4 h1:Tgh3Yr67PaOv/uTqloMsCEdeuFTatm5zIq5+qNN23vI= +github.com/prometheus/client_golang v1.20.4/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -615,8 +617,8 @@ 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.59.1 h1:LXb1quJHWm1P6wq/U824uxYi4Sg0oGvNeUm1z5dJoX0= -github.com/prometheus/common v0.59.1/go.mod h1:GpWM7dewqmVYcd7SmRaiWVe9SSqjf0UrwnYnpEZNuT0= +github.com/prometheus/common v0.60.0 h1:+V9PAREWNvJMAuJ1x1BaWl9dewMW4YrHZQbx0sJNllA= +github.com/prometheus/common v0.60.0/go.mod h1:h0LYf1R1deLSKtD4Vdg8gy4RuOvENW2J/h19V5NADQw= 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= @@ -945,10 +947,10 @@ google.golang.org/genproto v0.0.0-20210126160654-44e461bb6506/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20220314164441-57ef72a4c106/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E= google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de h1:F6qOa9AZTYJXOUEr4jDysRDLrm4PHePlge4v4TGAlxY= google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:VUhTRKeHn9wwcdrk73nvdC9gF178Tzhmt/qyaFcPLSo= -google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 h1:+rdxYoE3E5htTEWIe15GlN6IfvbURM//Jt0mmkmm6ZU= -google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117/go.mod h1:OimBR/bc1wPO9iV4NC2bpyjy3VnAwZh5EBPQdtaE5oo= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:pPJltXNxVzT4pK9yD8vR9X75DaWYYmLGMsEvBfFQZzQ= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= +google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 h1:wKguEg1hsxI2/L3hUYrpo1RVi48K+uTyzKqprwLXsb8= +google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142/go.mod h1:d6be+8HhtEtucleCbxpPW9PA9XwISACu8nvpPqF0BVo= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f h1:cUMEy+8oS78BWIH9OWazBkzbr090Od9tWBNtZHkOhf0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= 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.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= @@ -966,8 +968,8 @@ google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTp google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= -google.golang.org/grpc v1.66.2 h1:3QdXkuq3Bkh7w+ywLdLvM56cmGvQHUMZpiCzt6Rqaoo= -google.golang.org/grpc v1.66.2/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y= +google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E= +google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= 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= diff --git a/tests/systemtests/gov_test.go b/tests/systemtests/gov_test.go new file mode 100644 index 000000000000..092773dc2053 --- /dev/null +++ b/tests/systemtests/gov_test.go @@ -0,0 +1,415 @@ +//go:build system_test + +package systemtests + +import ( + "encoding/base64" + "fmt" + "testing" + "time" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/tidwall/gjson" + + "cosmossdk.io/math" + + "github.com/cosmos/cosmos-sdk/client/flags" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +func TestSubmitProposal(t *testing.T) { + // given a running chain + + sut.ResetChain(t) + cli := NewCLIWrapper(t, sut, verbose) + + // get validator address + valAddr := gjson.Get(cli.Keys("keys", "list"), "0.address").String() + require.NotEmpty(t, valAddr) + + sut.StartChain(t) + + // get gov module address + resp := cli.CustomQuery("q", "auth", "module-account", "gov") + govAddress := gjson.Get(resp, "account.value.address").String() + + invalidProp := `{ + "title": "", + "description": "Where is the title!?", + "type": "Text", + "deposit": "-324foocoin" +}` + + invalidPropFile := StoreTempFile(t, []byte(invalidProp)) + defer invalidPropFile.Close() + + // Create a valid new proposal JSON. + propMetadata := []byte{42} + validProp := fmt.Sprintf(` +{ + "messages": [ + { + "@type": "/cosmos.gov.v1.MsgExecLegacyContent", + "authority": "%s", + "content": { + "@type": "/cosmos.gov.v1beta1.TextProposal", + "title": "My awesome title", + "description": "My awesome description" + } + } + ], + "title": "My awesome title", + "summary": "My awesome description", + "metadata": "%s", + "deposit": "%s" +}`, govAddress, base64.StdEncoding.EncodeToString(propMetadata), sdk.NewCoin("stake", math.NewInt(100000))) + validPropFile := StoreTempFile(t, []byte(validProp)) + defer validPropFile.Close() + + testCases := []struct { + name string + args []string + expectErr bool + errMsg string + }{ + { + "invalid proposal", + []string{ + "tx", "gov", "submit-proposal", + invalidPropFile.Name(), + fmt.Sprintf("--%s=%s", flags.FlagFrom, valAddr), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(10))).String()), + }, + true, + "invalid character in coin string", + }, + { + "valid proposal", + []string{ + "tx", "gov", "submit-proposal", + validPropFile.Name(), + fmt.Sprintf("--%s=%s", flags.FlagFrom, valAddr), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(10))).String()), + }, + false, + "", + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + if tc.expectErr { + assertOutput := func(_ assert.TestingT, gotErr error, gotOutputs ...interface{}) bool { + require.Contains(t, gotOutputs[0], tc.errMsg) + return false + } + + cli.WithRunErrorMatcher(assertOutput).Run(tc.args...) + } else { + rsp := cli.Run(tc.args...) + txResult, found := cli.AwaitTxCommitted(rsp) + require.True(t, found) + RequireTxSuccess(t, txResult) + } + }) + } +} + +func TestSubmitLegacyProposal(t *testing.T) { + // given a running chain + + sut.ResetChain(t) + cli := NewCLIWrapper(t, sut, verbose) + + // get validator address + valAddr := gjson.Get(cli.Keys("keys", "list"), "0.address").String() + require.NotEmpty(t, valAddr) + + sut.StartChain(t) + + invalidProp := `{ + "title": "", + "description": "Where is the title!?", + "type": "Text", + "deposit": "-324foocoin" + }` + invalidPropFile := StoreTempFile(t, []byte(invalidProp)) + defer invalidPropFile.Close() + + validProp := fmt.Sprintf(`{ + "title": "Text Proposal", + "description": "Hello, World!", + "type": "Text", + "deposit": "%s" + }`, sdk.NewCoin("stake", math.NewInt(154310))) + validPropFile := StoreTempFile(t, []byte(validProp)) + defer validPropFile.Close() + + testCases := []struct { + name string + args []string + expectErr bool + errMsg string + }{ + { + "invalid proposal (file)", + []string{ + "tx", "gov", "submit-legacy-proposal", + fmt.Sprintf("--%s=%s", "proposal", invalidPropFile.Name()), + fmt.Sprintf("--%s=%s", flags.FlagFrom, valAddr), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(10))).String()), + }, + true, + "proposal title is required", + }, + { + "invalid proposal", + []string{ + "tx", "gov", "submit-legacy-proposal", + fmt.Sprintf("--%s='Where is the title!?'", "description"), + fmt.Sprintf("--%s=%s", "type", "Text"), + fmt.Sprintf("--%s=%s", "deposit", sdk.NewCoin("stake", math.NewInt(10000)).String()), + fmt.Sprintf("--%s=%s", flags.FlagFrom, valAddr), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(10))).String()), + }, + true, + "proposal title is required", + }, + { + "valid transaction (file)", + []string{ + "tx", "gov", "submit-legacy-proposal", + fmt.Sprintf("--%s=%s", "proposal", validPropFile.Name()), + fmt.Sprintf("--%s=%s", flags.FlagFrom, valAddr), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(10))).String()), + }, + false, + "", + }, + { + "valid transaction", + []string{ + "tx", "gov", "submit-legacy-proposal", + fmt.Sprintf("--%s='Text Proposal'", "title"), + fmt.Sprintf("--%s='Where is the title!?'", "description"), + fmt.Sprintf("--%s=%s", "type", "Text"), + fmt.Sprintf("--%s=%s", "deposit", sdk.NewCoin("stake", math.NewInt(100000)).String()), + fmt.Sprintf("--%s=%s", flags.FlagFrom, valAddr), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(10))).String()), + }, + false, + "", + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + if tc.expectErr { + assertOutput := func(_ assert.TestingT, gotErr error, gotOutputs ...interface{}) bool { + fmt.Println("gotOut", gotOutputs) + require.Contains(t, gotOutputs[0], tc.errMsg) + return false + } + + cli.WithRunErrorMatcher(assertOutput).Run(tc.args...) + } else { + rsp := cli.Run(tc.args...) + txResult, found := cli.AwaitTxCommitted(rsp) + require.True(t, found) + RequireTxSuccess(t, txResult) + } + }) + } +} + +func TestNewCmdWeightedVote(t *testing.T) { + // given a running chain + + sut.ResetChain(t) + cli := NewCLIWrapper(t, sut, verbose) + + // get validator address + valAddr := gjson.Get(cli.Keys("keys", "list"), "0.address").String() + require.NotEmpty(t, valAddr) + + sut.StartChain(t) + + // Submit a new proposal for voting + proposalArgs := []string{ + "tx", "gov", "submit-legacy-proposal", + fmt.Sprintf("--%s='Text Proposal'", "title"), + fmt.Sprintf("--%s='Where is the title!?'", "description"), + fmt.Sprintf("--%s=%s", "type", "Text"), + fmt.Sprintf("--%s=%s", "deposit", sdk.NewCoin("stake", math.NewInt(10_000_000)).String()), + fmt.Sprintf("--%s=%s", flags.FlagFrom, valAddr), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(10))).String()), + } + rsp := cli.Run(proposalArgs...) + txResult, found := cli.AwaitTxCommitted(rsp) + require.True(t, found) + RequireTxSuccess(t, txResult) + + proposalsResp := cli.CustomQuery("q", "gov", "proposals") + proposals := gjson.Get(proposalsResp, "proposals.#.id").Array() + require.NotEmpty(t, proposals) + + proposal1 := cli.CustomQuery("q", "gov", "proposal", "1") + fmt.Println("first proposal", proposal1) + + testCases := []struct { + name string + args []string + expectErr bool + expectedCode uint32 + broadcasted bool + errMsg string + }{ + { + "vote for invalid proposal", + []string{ + "tx", "gov", "weighted-vote", + "10", + "yes", + fmt.Sprintf("--%s=%s", flags.FlagFrom, valAddr), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(10))).String()), + }, + true, 3, true, + "inactive proposal", + }, + { + "valid vote", + []string{ + "tx", "gov", "weighted-vote", + "1", + "yes", + fmt.Sprintf("--%s=%s", flags.FlagFrom, valAddr), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(10))).String()), + }, + false, 0, true, + "", + }, + { + "valid vote with metadata", + []string{ + "tx", "gov", "weighted-vote", + "1", + "yes", + fmt.Sprintf("--%s=%s", flags.FlagFrom, valAddr), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), + fmt.Sprintf("--metadata=%s", "AQ=="), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(10))).String()), + }, + false, 0, true, + "", + }, + { + "invalid valid split vote string", + []string{ + "tx", "gov", "weighted-vote", + "1", + "yes/0.6,no/0.3,abstain/0.05,no_with_veto/0.05", + fmt.Sprintf("--%s=%s", flags.FlagFrom, valAddr), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(10))).String()), + }, + true, 0, false, + "is not a valid vote option", + }, + { + "valid split vote", + []string{ + "tx", "gov", "weighted-vote", + "1", + "yes=0.6,no=0.3,abstain=0.05,no_with_veto=0.05", + fmt.Sprintf("--%s=%s", flags.FlagFrom, valAddr), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(10))).String()), + }, + false, 0, true, + "", + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + if !tc.broadcasted { + assertOutput := func(_ assert.TestingT, gotErr error, gotOutputs ...interface{}) bool { + require.Contains(t, gotOutputs[0], tc.errMsg) + return false + } + cli.WithRunErrorMatcher(assertOutput).Run(tc.args...) + } else { + rsp := cli.Run(tc.args...) + if tc.expectErr { + RequireTxFailure(t, rsp) + } else { + cli.AwaitTxCommitted(rsp) + } + } + }) + } +} + +func TestQueryDeposit(t *testing.T) { + // given a running chain + + sut.ResetChain(t) + cli := NewCLIWrapper(t, sut, verbose) + + // get validator address + valAddr := gjson.Get(cli.Keys("keys", "list"), "0.address").String() + require.NotEmpty(t, valAddr) + + sut.StartChain(t) + + // Submit a new proposal for voting + proposalArgs := []string{ + "tx", "gov", "submit-legacy-proposal", + fmt.Sprintf("--%s='Text Proposal'", "title"), + fmt.Sprintf("--%s='Where is the title!?'", "description"), + fmt.Sprintf("--%s=%s", "type", "Text"), + fmt.Sprintf("--%s=%s", "deposit", sdk.NewCoin("stake", math.NewInt(10_000_000)).String()), + fmt.Sprintf("--%s=%s", flags.FlagFrom, valAddr), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(10))).String()), + } + rsp := cli.Run(proposalArgs...) + txResult, found := cli.AwaitTxCommitted(rsp) + require.True(t, found) + RequireTxSuccess(t, txResult) + + // Query initial deposit + resp := cli.CustomQuery("q", "gov", "deposit", "1", valAddr) + depositAmount := gjson.Get(resp, "deposit.amount.0.amount").Int() + require.Equal(t, depositAmount, int64(10_000_000)) + + resp = cli.CustomQuery("q", "gov", "deposits", "1") + deposits := gjson.Get(resp, "deposits").Array() + require.Equal(t, len(deposits), 1) + + time.Sleep(time.Second * 8) + resp = cli.CustomQuery("q", "gov", "deposits", "1") + deposits = gjson.Get(resp, "deposits").Array() + require.Equal(t, len(deposits), 0) +} diff --git a/tests/systemtests/io_utils.go b/tests/systemtests/io_utils.go new file mode 100644 index 000000000000..a9cd1094fba6 --- /dev/null +++ b/tests/systemtests/io_utils.go @@ -0,0 +1,65 @@ +package systemtests + +import ( + "bytes" + "fmt" + "io" + "os" + "path/filepath" + "testing" + + "github.com/stretchr/testify/require" +) + +// MustCopyFile copies the file from the source path `src` to the destination path `dest` and returns an open file handle to `dest`. +func MustCopyFile(src, dest string) *os.File { + in, err := os.Open(src) + if err != nil { + panic(fmt.Sprintf("failed to open %q: %v", src, err)) + } + defer in.Close() + + out, err := os.Create(dest) + if err != nil { + panic(fmt.Sprintf("failed to create %q: %v", dest, err)) + } + defer out.Close() + + _, err = io.Copy(out, in) + if err != nil { + panic(fmt.Sprintf("failed to copy from %q to %q: %v", src, dest, err)) + } + return out +} + +// MustCopyFilesInDir copies all files (excluding directories) from the source directory `src` to the destination directory `dest`. +func MustCopyFilesInDir(src, dest string) { + err := os.MkdirAll(dest, 0o750) + if err != nil { + panic(fmt.Sprintf("failed to create %q: %v", dest, err)) + } + + fs, err := os.ReadDir(src) + if err != nil { + panic(fmt.Sprintf("failed to read dir %q: %v", src, err)) + } + + for _, f := range fs { + if f.IsDir() { + continue + } + _ = MustCopyFile(filepath.Join(src, f.Name()), filepath.Join(dest, f.Name())) + } +} + +// StoreTempFile creates a temporary file in the test's temporary directory with the provided content. +// It returns a pointer to the created file. Errors during the process are handled with test assertions. +func StoreTempFile(t *testing.T, content []byte) *os.File { + t.Helper() + out, err := os.CreateTemp(t.TempDir(), "") + require.NoError(t, err) + _, err = io.Copy(out, bytes.NewReader(content)) + require.NoError(t, err) + require.NoError(t, out.Close()) + return out +} diff --git a/tests/systemtests/rest_cli.go b/tests/systemtests/rest_cli.go new file mode 100644 index 000000000000..2ae879e1a242 --- /dev/null +++ b/tests/systemtests/rest_cli.go @@ -0,0 +1,56 @@ +package systemtests + +import ( + "io" + "net/http" + "testing" + + "github.com/stretchr/testify/require" +) + +type RestTestCase struct { + name string + url string + expCode int + expOut string +} + +// RunRestQueries runs given Rest testcases by making requests and +// checking response with expected output +func RunRestQueries(t *testing.T, testCases []RestTestCase) { + t.Helper() + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + resp := GetRequestWithHeaders(t, tc.url, nil, tc.expCode) + require.JSONEq(t, tc.expOut, string(resp)) + }) + } +} + +func GetRequest(t *testing.T, url string) []byte { + t.Helper() + return GetRequestWithHeaders(t, url, nil, http.StatusOK) +} + +func GetRequestWithHeaders(t *testing.T, url string, headers map[string]string, expCode int) []byte { + t.Helper() + req, err := http.NewRequest("GET", url, nil) + require.NoError(t, err) + + for key, value := range headers { + req.Header.Set(key, value) + } + + httpClient := &http.Client{} + res, err := httpClient.Do(req) + require.NoError(t, err) + defer func() { + _ = res.Body.Close() + }() + require.Equal(t, expCode, res.StatusCode, "status code should be %d, got: %d", expCode, res.StatusCode) + + body, err := io.ReadAll(res.Body) + require.NoError(t, err) + return body +} diff --git a/tests/systemtests/rpc_client.go b/tests/systemtests/rpc_client.go index d1acfd780ff4..4714715be600 100644 --- a/tests/systemtests/rpc_client.go +++ b/tests/systemtests/rpc_client.go @@ -2,11 +2,23 @@ package systemtests import ( "context" + "errors" + "reflect" + "strconv" "testing" + abci "github.com/cometbft/cometbft/api/cometbft/abci/v1" + rpcclient "github.com/cometbft/cometbft/rpc/client" client "github.com/cometbft/cometbft/rpc/client/http" cmtypes "github.com/cometbft/cometbft/types" "github.com/stretchr/testify/require" + "google.golang.org/grpc" + "google.golang.org/grpc/metadata" + + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/codec/types" + cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" + grpctypes "github.com/cosmos/cosmos-sdk/types/grpc" ) // RPCClient is a test helper to interact with a node via the RPC endpoint. @@ -31,3 +43,71 @@ func (r RPCClient) Validators() []*cmtypes.Validator { require.NoError(r.t, err) return v.Validators } + +func (r RPCClient) Invoke(ctx context.Context, method string, req, reply interface{}, opts ...grpc.CallOption) error { + if reflect.ValueOf(req).IsNil() { + return errors.New("request cannot be nil") + } + + ir := types.NewInterfaceRegistry() + cryptocodec.RegisterInterfaces(ir) + cdc := codec.NewProtoCodec(ir).GRPCCodec() + + reqBz, err := cdc.Marshal(req) + if err != nil { + return err + } + + var height int64 + md, _ := metadata.FromOutgoingContext(ctx) + if heights := md.Get(grpctypes.GRPCBlockHeightHeader); len(heights) > 0 { + height, err := strconv.ParseInt(heights[0], 10, 64) + if err != nil { + return err + } + if height < 0 { + return errors.New("height must be greater than or equal to 0") + } + } + + abciReq := abci.QueryRequest{ + Path: method, + Data: reqBz, + Height: height, + } + + abciOpts := rpcclient.ABCIQueryOptions{ + Height: height, + Prove: abciReq.Prove, + } + + result, err := r.client.ABCIQueryWithOptions(ctx, abciReq.Path, abciReq.Data, abciOpts) + if err != nil { + return err + } + + if !result.Response.IsOK() { + return errors.New(result.Response.String()) + } + + err = cdc.Unmarshal(result.Response.Value, reply) + if err != nil { + return err + } + + md = metadata.Pairs(grpctypes.GRPCBlockHeightHeader, strconv.FormatInt(result.Response.Height, 10)) + for _, callOpt := range opts { + header, ok := callOpt.(grpc.HeaderCallOption) + if !ok { + continue + } + + *header.HeaderAddr = md + } + + return types.UnpackInterfaces(reply, ir) +} + +func (r RPCClient) NewStream(ctx context.Context, desc *grpc.StreamDesc, method string, opts ...grpc.CallOption) (grpc.ClientStream, error) { + return nil, errors.New("not implemented") +} diff --git a/tests/systemtests/snapshots_test.go b/tests/systemtests/snapshots_test.go new file mode 100644 index 000000000000..d80eb530f413 --- /dev/null +++ b/tests/systemtests/snapshots_test.go @@ -0,0 +1,98 @@ +//go:build system_test + +package systemtests + +import ( + "fmt" + "os" + "testing" + + "github.com/stretchr/testify/require" +) + +func TestSnapshots(t *testing.T) { + sut.ResetChain(t) + cli := NewCLIWrapper(t, sut, verbose) + sut.StartChain(t) + + // Wait for chain produce some blocks + sut.AwaitNBlocks(t, 6) + // Stop all nodes + sut.StopChain() + + var ( + command string + restoreableDirs []string + ) + node0Dir := sut.NodeDir(0) + if isV2() { + command = "store" + restoreableDirs = []string{fmt.Sprintf("%s/data/application.db", node0Dir), fmt.Sprintf("%s/data/ss", node0Dir)} + } else { + command = "snapshots" + restoreableDirs = []string{fmt.Sprintf("%s/data/application.db", node0Dir)} + } + + // export snapshot at height 5 + res := cli.RunCommandWithArgs(command, "export", "--height=5", fmt.Sprintf("--home=%s", node0Dir)) + require.Contains(t, res, "Snapshot created at height 5") + require.DirExists(t, fmt.Sprintf("%s/data/snapshots/5/3", node0Dir)) + + // Check snapshots list + res = cli.RunCommandWithArgs(command, "list", fmt.Sprintf("--home=%s", node0Dir)) + require.Contains(t, res, "height: 5") + + // Dump snapshot + res = cli.RunCommandWithArgs(command, "dump", "5", "3", fmt.Sprintf("--home=%s", node0Dir), fmt.Sprintf("--output=%s/5-3.tar.gz", node0Dir)) + // Check if output file exist + require.FileExists(t, fmt.Sprintf("%s/5-3.tar.gz", node0Dir)) + + // Delete snapshots + res = cli.RunCommandWithArgs(command, "delete", "5", "3", fmt.Sprintf("--home=%s", node0Dir)) + require.NoDirExists(t, fmt.Sprintf("%s/data/snapshots/5/3", node0Dir)) + + // Load snapshot from file + res = cli.RunCommandWithArgs(command, "load", fmt.Sprintf("%s/5-3.tar.gz", node0Dir), fmt.Sprintf("--home=%s", node0Dir)) + require.DirExists(t, fmt.Sprintf("%s/data/snapshots/5/3", node0Dir)) + + // Restore from snapshots + for _, dir := range restoreableDirs { + require.NoError(t, os.RemoveAll(dir)) + } + // Remove database + err := os.RemoveAll(fmt.Sprintf("%s/data/application.db", node0Dir)) + require.NoError(t, err) + if isV2() { + require.NoError(t, os.RemoveAll(fmt.Sprintf("%s/data/ss", node0Dir))) + } + + res = cli.RunCommandWithArgs(command, "restore", "5", "3", fmt.Sprintf("--home=%s", node0Dir)) + for _, dir := range restoreableDirs { + require.DirExists(t, dir) + } +} + +func TestPrune(t *testing.T) { + sut.ResetChain(t) + cli := NewCLIWrapper(t, sut, verbose) + + sut.StartChain(t) + + // Wait for chain produce some blocks + sut.AwaitNBlocks(t, 6) + + // Stop all nodes + sut.StopChain() + + node0Dir := sut.NodeDir(0) + + // prune + var command []string + if isV2() { + command = []string{"store", "prune", "--keep-recent=1"} + } else { + command = []string{"prune", "everything"} + } + res := cli.RunCommandWithArgs(append(command, fmt.Sprintf("--home=%s", node0Dir))...) + require.Contains(t, res, "successfully pruned the application root multi stores") +} diff --git a/tests/systemtests/staking_test.go b/tests/systemtests/staking_test.go index 5f8f911191bc..58b6c863a744 100644 --- a/tests/systemtests/staking_test.go +++ b/tests/systemtests/staking_test.go @@ -12,6 +12,7 @@ import ( func TestStakeUnstake(t *testing.T) { // Scenario: // delegate tokens to validator + // check validator has been updated // undelegate some tokens sut.ResetChain(t) @@ -29,16 +30,24 @@ func TestStakeUnstake(t *testing.T) { // query validator address to delegate tokens rsp := cli.CustomQuery("q", "staking", "validators") valAddr := gjson.Get(rsp, "validators.#.operator_address").Array()[0].String() + valPk := gjson.Get(rsp, "validators.#.consensus_pubkey.value").Array()[0].String() // stake tokens - rsp = cli.RunAndWait("tx", "staking", "delegate", valAddr, "10000stake", "--from="+account1Addr, "--fees=1stake") + rsp = cli.RunAndWait("tx", "staking", "delegate", valAddr, "1000000stake", "--from="+account1Addr, "--fees=1stake") RequireTxSuccess(t, rsp) t.Log(cli.QueryBalance(account1Addr, "stake")) - assert.Equal(t, int64(9989999), cli.QueryBalance(account1Addr, "stake")) + assert.Equal(t, int64(8999999), cli.QueryBalance(account1Addr, "stake")) + + // check validator has been updated + rsp = cli.CustomQuery("q", "block-results", gjson.Get(rsp, "height").String()) + validatorUpdates := gjson.Get(rsp, "validator_updates").Array() + assert.NotEmpty(t, validatorUpdates) + vpk := gjson.Get(validatorUpdates[0].String(), "pub_key_bytes").String() + assert.Equal(t, vpk, valPk) rsp = cli.CustomQuery("q", "staking", "delegation", account1Addr, valAddr) - assert.Equal(t, "10000", gjson.Get(rsp, "delegation_response.balance.amount").String(), rsp) + assert.Equal(t, "1000000", gjson.Get(rsp, "delegation_response.balance.amount").String(), rsp) assert.Equal(t, "stake", gjson.Get(rsp, "delegation_response.balance.denom").String(), rsp) // unstake tokens @@ -46,7 +55,7 @@ func TestStakeUnstake(t *testing.T) { RequireTxSuccess(t, rsp) rsp = cli.CustomQuery("q", "staking", "delegation", account1Addr, valAddr) - assert.Equal(t, "5000", gjson.Get(rsp, "delegation_response.balance.amount").String(), rsp) + assert.Equal(t, "995000", gjson.Get(rsp, "delegation_response.balance.amount").String(), rsp) assert.Equal(t, "stake", gjson.Get(rsp, "delegation_response.balance.denom").String(), rsp) rsp = cli.CustomQuery("q", "staking", "unbonding-delegation", account1Addr, valAddr) diff --git a/tests/systemtests/system.go b/tests/systemtests/system.go index 8505d20d7868..7aa00f7cfbf3 100644 --- a/tests/systemtests/system.go +++ b/tests/systemtests/system.go @@ -53,6 +53,7 @@ type SystemUnderTest struct { // since Tendermint consensus does not allow specifying it directly. blockTime time.Duration rpcAddr string + apiAddr string initialNodesCount int nodesCount int minGasPrice string @@ -86,6 +87,7 @@ func NewSystemUnderTest(execBinary string, verbose bool, nodesCount int, blockTi outputDir: "./testnet", blockTime: blockTime, rpcAddr: "tcp://localhost:26657", + apiAddr: fmt.Sprintf("http://localhost:%d", apiPortStart), initialNodesCount: nodesCount, outBuff: ring.New(100), errBuff: ring.New(100), @@ -132,6 +134,11 @@ func (s *SystemUnderTest) SetupChain() { if err != nil { panic(fmt.Sprintf("failed set block max gas: %s", err)) } + // Short period for gov + genesisBz, err = sjson.SetRawBytes(genesisBz, "app_state.gov.params.voting_period", []byte(fmt.Sprintf(`"%s"`, "8s"))) + if err != nil { + panic(fmt.Sprintf("failed set block max gas: %s", err)) + } s.withEachNodeHome(func(i int, home string) { if err := saveGenesis(home, genesisBz); err != nil { panic(err) @@ -140,15 +147,11 @@ func (s *SystemUnderTest) SetupChain() { // backup genesis dest := filepath.Join(WorkDir, s.nodePath(0), "config", "genesis.json.orig") - if _, err := copyFile(src, dest); err != nil { - panic(fmt.Sprintf("copy failed :%#+v", err)) - } + MustCopyFile(src, dest) // backup keyring src = filepath.Join(WorkDir, s.nodePath(0), "keyring-test") dest = filepath.Join(WorkDir, s.outputDir, "keyring-test") - if err := copyFilesInDir(src, dest); err != nil { - panic(fmt.Sprintf("copy files from dir :%#+v", err)) - } + MustCopyFilesInDir(src, dest) } func (s *SystemUnderTest) StartChain(t *testing.T, xargs ...string) { @@ -360,7 +363,13 @@ func (s *SystemUnderTest) PrintBuffer() { }) } -// AwaitBlockHeight blocks until te target height is reached. An optional timeout parameter can be passed to abort early +// AwaitNBlocks blocks until the current height + n block is reached. An optional timeout parameter can be passed to abort early +func (s *SystemUnderTest) AwaitNBlocks(t *testing.T, n int64, timeout ...time.Duration) { + t.Helper() + s.AwaitBlockHeight(t, s.CurrentHeight()+n, timeout...) +} + +// AwaitBlockHeight blocks until the target height is reached. An optional timeout parameter can be passed to abort early func (s *SystemUnderTest) AwaitBlockHeight(t *testing.T, targetHeight int64, timeout ...time.Duration) { t.Helper() require.Greater(t, targetHeight, s.currentHeight.Load()) @@ -472,7 +481,7 @@ func (s *SystemUnderTest) modifyGenesisJSON(t *testing.T, mutators ...GenesisMut for _, m := range mutators { current = m(current) } - out := storeTempFile(t, current) + out := StoreTempFile(t, current) defer os.Remove(out.Name()) s.setGenesis(t, out.Name()) s.MarkDirty() @@ -577,6 +586,7 @@ func (s *SystemUnderTest) startNodesAsync(t *testing.T, xargs ...string) { }) } +// tracks the PID in state with a go routine waiting for the shutdown completion to unregister func (s *SystemUnderTest) awaitProcessCleanup(cmd *exec.Cmd) { pid := cmd.Process.Pid s.pidsLock.Lock() @@ -597,6 +607,11 @@ func (s *SystemUnderTest) withEachNodeHome(cb func(i int, home string)) { } } +// NodeDir returns the workdir and path to the node home folder. +func (s *SystemUnderTest) NodeDir(i int) string { + return filepath.Join(WorkDir, s.nodePath(i)) +} + // nodePath returns the path of the node within the work dir. not absolute func (s *SystemUnderTest) nodePath(i int) string { return NodePath(i, s.outputDir, s.projectName) @@ -621,6 +636,10 @@ func (s *SystemUnderTest) RPCClient(t *testing.T) RPCClient { return NewRPCClient(t, s.rpcAddr) } +func (s *SystemUnderTest) APIAddress() string { + return s.apiAddr +} + func (s *SystemUnderTest) AllPeers(t *testing.T) []string { t.Helper() result := make([]string, s.nodesCount) @@ -689,8 +708,7 @@ func (s *SystemUnderTest) AddFullnode(t *testing.T, beforeStart ...func(nodeNumb for _, tomlFile := range []string{"config.toml", "app.toml"} { configFile := filepath.Join(configPath, tomlFile) _ = os.Remove(configFile) - _, err := copyFile(filepath.Join(WorkDir, s.nodePath(0), "config", tomlFile), configFile) - require.NoError(t, err) + _ = MustCopyFile(filepath.Join(WorkDir, s.nodePath(0), "config", tomlFile), configFile) } // start node allNodes := s.AllNodes(t) @@ -926,54 +944,6 @@ func restoreOriginalKeyring(t *testing.T, s *SystemUnderTest) { require.NoError(t, os.RemoveAll(dest)) for i := 0; i < s.initialNodesCount; i++ { src := filepath.Join(WorkDir, s.nodePath(i), "keyring-test") - require.NoError(t, copyFilesInDir(src, dest)) - } -} - -// copyFile copy source file to dest file path -func copyFile(src, dest string) (*os.File, error) { - in, err := os.Open(src) - if err != nil { - return nil, err - } - defer in.Close() - out, err := os.Create(dest) - if err != nil { - return nil, err + MustCopyFilesInDir(src, dest) } - defer out.Close() - - _, err = io.Copy(out, in) - return out, err -} - -// copyFilesInDir copy files in src dir to dest path -func copyFilesInDir(src, dest string) error { - err := os.MkdirAll(dest, 0o750) - if err != nil { - return fmt.Errorf("mkdirs: %w", err) - } - fs, err := os.ReadDir(src) - if err != nil { - return fmt.Errorf("read dir: %w", err) - } - for _, f := range fs { - if f.IsDir() { - continue - } - if _, err := copyFile(filepath.Join(src, f.Name()), filepath.Join(dest, f.Name())); err != nil { - return fmt.Errorf("copy file: %q: %w", f.Name(), err) - } - } - return nil -} - -func storeTempFile(t *testing.T, content []byte) *os.File { - t.Helper() - out, err := os.CreateTemp(t.TempDir(), "genesis") - require.NoError(t, err) - _, err = io.Copy(out, bytes.NewReader(content)) - require.NoError(t, err) - require.NoError(t, out.Close()) - return out } diff --git a/tests/systemtests/testnet_init.go b/tests/systemtests/testnet_init.go index c3cd9c0f73e7..bdb2a85d25da 100644 --- a/tests/systemtests/testnet_init.go +++ b/tests/systemtests/testnet_init.go @@ -13,6 +13,12 @@ import ( "github.com/creachadair/tomledit/parser" ) +// isV2 checks if the tests run with simapp v2 +func isV2() bool { + buildOptions := os.Getenv("COSMOS_BUILD_OPTIONS") + return strings.Contains(buildOptions, "v2") +} + // SingleHostTestnetCmdInitializer default testnet cmd that supports the --single-host param type SingleHostTestnetCmdInitializer struct { execBinary string @@ -53,10 +59,16 @@ func (s SingleHostTestnetCmdInitializer) Initialize() { "--output-dir=" + s.outputDir, "--validator-count=" + strconv.Itoa(s.initialNodesCount), "--keyring-backend=test", - "--minimum-gas-prices=" + s.minGasPrice, "--commit-timeout=" + s.commitTimeout.String(), "--single-host", } + + if isV2() { + args = append(args, "--server.minimum-gas-prices="+s.minGasPrice) + } else { + args = append(args, "--minimum-gas-prices="+s.minGasPrice) + } + s.log(fmt.Sprintf("+++ %s %s\n", s.execBinary, strings.Join(args, " "))) out, err := RunShellCmd(s.execBinary, args...) if err != nil { @@ -108,8 +120,14 @@ func (s ModifyConfigYamlInitializer) Initialize() { "--output-dir=" + s.outputDir, "--v=" + strconv.Itoa(s.initialNodesCount), "--keyring-backend=test", - "--minimum-gas-prices=" + s.minGasPrice, } + + if isV2() { + args = append(args, "--server.minimum-gas-prices="+s.minGasPrice) + } else { + args = append(args, "--minimum-gas-prices="+s.minGasPrice) + } + s.log(fmt.Sprintf("+++ %s %s\n", s.execBinary, strings.Join(args, " "))) out, err := RunShellCmd(s.execBinary, args...) @@ -144,7 +162,6 @@ func (s ModifyConfigYamlInitializer) Initialize() { EditToml(filepath.Join(nodeDir, "app.toml"), func(doc *tomledit.Document) { UpdatePort(doc, apiPortStart+i, "api", "address") UpdatePort(doc, grpcPortStart+i, "grpc", "address") - SetBool(doc, true, "grpc-web", "enable") }) } } diff --git a/tests/systemtests/unordered_tx_test.go b/tests/systemtests/unordered_tx_test.go index 6b1a9c743e7d..579552efe0e7 100644 --- a/tests/systemtests/unordered_tx_test.go +++ b/tests/systemtests/unordered_tx_test.go @@ -12,7 +12,8 @@ import ( ) func TestUnorderedTXDuplicate(t *testing.T) { - t.Skip("The unordered tx antehanlder is missing in v2") + t.Skip("The unordered tx handling is not wired in v2") + // scenario: test unordered tx duplicate // given a running chain with a tx in the unordered tx pool // when a new tx with the same hash is broadcasted diff --git a/tests/systemtests/upgrade_test.go b/tests/systemtests/upgrade_test.go index a9a990ef2819..bd719d1e7962 100644 --- a/tests/systemtests/upgrade_test.go +++ b/tests/systemtests/upgrade_test.go @@ -38,7 +38,7 @@ func TestChainUpgrade(t *testing.T) { upgradeName = "v050-to-v051" ) - sut.StartChain(t, fmt.Sprintf("--halt-height=%d", upgradeHeight)) + sut.StartChain(t, fmt.Sprintf("--halt-height=%d", upgradeHeight+1)) cli := NewCLIWrapper(t, sut, verbose) govAddr := sdk.AccAddress(address.Module("gov")).String() diff --git a/testutil/configurator/configurator.go b/testutil/configurator/configurator.go index 91c93ba2d5b0..f6114e704f1f 100644 --- a/testutil/configurator/configurator.go +++ b/testutil/configurator/configurator.go @@ -24,11 +24,16 @@ import ( slashingmodulev1 "cosmossdk.io/api/cosmos/slashing/module/v1" stakingmodulev1 "cosmossdk.io/api/cosmos/staking/module/v1" txconfigv1 "cosmossdk.io/api/cosmos/tx/config/v1" + validatemodulev1 "cosmossdk.io/api/cosmos/validate/module/v1" vestingmodulev1 "cosmossdk.io/api/cosmos/vesting/module/v1" "cosmossdk.io/depinject" "cosmossdk.io/depinject/appconfig" "github.com/cosmos/cosmos-sdk/testutil" + _ "github.com/cosmos/cosmos-sdk/x/auth" // import as blank for app wiring + _ "github.com/cosmos/cosmos-sdk/x/auth/tx/config" // import as blank for app wiring + _ "github.com/cosmos/cosmos-sdk/x/genutil" // import as blank for app wiring + _ "github.com/cosmos/cosmos-sdk/x/validate" // import as blank for app wiring ) // Config should never need to be instantiated manually and is solely used for ModuleOption. @@ -183,13 +188,22 @@ func ParamsModule() ModuleOption { func TxModule() ModuleOption { return func(config *Config) { - config.ModuleConfigs[testutil.TxModuleName] = &appv1alpha1.ModuleConfig{ - Name: testutil.TxModuleName, + config.ModuleConfigs[testutil.AuthTxConfigDepinjectModuleName] = &appv1alpha1.ModuleConfig{ + Name: testutil.AuthTxConfigDepinjectModuleName, Config: appconfig.WrapAny(&txconfigv1.Config{}), } } } +func ValidateModule() ModuleOption { + return func(config *Config) { + config.ModuleConfigs[testutil.ValidateModuleName] = &appv1alpha1.ModuleConfig{ + Name: testutil.ValidateModuleName, + Config: appconfig.WrapAny(&validatemodulev1.Module{}), + } + } +} + func StakingModule() ModuleOption { return func(config *Config) { config.ModuleConfigs[testutil.StakingModuleName] = &appv1alpha1.ModuleConfig{ diff --git a/testutil/integration/router.go b/testutil/integration/router.go index f2427f02fd6e..07bbe3d4c206 100644 --- a/testutil/integration/router.go +++ b/testutil/integration/router.go @@ -55,6 +55,7 @@ func NewIntegrationApp( modules map[string]appmodule.AppModule, msgRouter *baseapp.MsgServiceRouter, grpcRouter *baseapp.GRPCQueryRouter, + baseAppOptions ...func(*baseapp.BaseApp), ) *App { db := coretesting.NewMemDB() @@ -63,7 +64,7 @@ func NewIntegrationApp( moduleManager.RegisterInterfaces(interfaceRegistry) txConfig := authtx.NewTxConfig(codec.NewProtoCodec(interfaceRegistry), addressCodec, validatorCodec, authtx.DefaultSignModes) - bApp := baseapp.NewBaseApp(appName, logger, db, txConfig.TxDecoder(), baseapp.SetChainID(appName)) + bApp := baseapp.NewBaseApp(appName, logger, db, txConfig.TxDecoder(), append(baseAppOptions, baseapp.SetChainID(appName))...) bApp.MountKVStores(keys) bApp.SetInitChainer(func(_ sdk.Context, _ *cmtabcitypes.InitChainRequest) (*cmtabcitypes.InitChainResponse, error) { diff --git a/testutil/network/network.go b/testutil/network/network.go index bfdedb23e358..2bc85a10bd52 100644 --- a/testutil/network/network.go +++ b/testutil/network/network.go @@ -493,7 +493,7 @@ func New(l Logger, baseDir string, cfg Config) (NetworkI, error) { sdk.ValAddress(addr).String(), valPubKeys[i], sdk.NewCoin(cfg.BondDenom, cfg.BondedTokens), - stakingtypes.NewDescription(nodeDirName, "", "", "", ""), + stakingtypes.NewDescription(nodeDirName, "", "", "", "", stakingtypes.Metadata{}), stakingtypes.NewCommissionRates(commission, sdkmath.LegacyOneDec(), sdkmath.LegacyOneDec()), sdkmath.OneInt(), ) diff --git a/testutil/sims/simulation_helpers.go b/testutil/sims/simulation_helpers.go index a513a783edcf..c3ac6b4c0895 100644 --- a/testutil/sims/simulation_helpers.go +++ b/testutil/sims/simulation_helpers.go @@ -7,79 +7,14 @@ import ( "os" "sync" - dbm "github.com/cosmos/cosmos-db" - corestore "cosmossdk.io/core/store" - "cosmossdk.io/log" storetypes "cosmossdk.io/store/types" - "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/runtime" - sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/kv" - "github.com/cosmos/cosmos-sdk/types/module" simtypes "github.com/cosmos/cosmos-sdk/types/simulation" ) -// SetupSimulation creates the config, db (levelDB), temporary directory and logger for the simulation tests. -// If `skip` is false it skips the current test. `skip` should be set using the `FlagEnabledValue` flag. -// Returns error on an invalid db instantiation or temp dir creation. -func SetupSimulation(config simtypes.Config, dirPrefix, dbName string, verbose, skip bool) (corestore.KVStoreWithBatch, string, log.Logger, bool, error) { - if !skip { - return nil, "", nil, true, nil - } - - var logger log.Logger - if verbose { - logger = log.NewLogger(os.Stdout) - } else { - logger = log.NewNopLogger() - } - - dir, err := os.MkdirTemp("", dirPrefix) - if err != nil { - return nil, "", nil, false, err - } - - db, err := dbm.NewDB(dbName, dbm.BackendType(config.DBBackend), dir) - if err != nil { - return nil, "", nil, false, err - } - - return db, dir, logger, false, nil -} - -// SimulationOperations retrieves the simulation params from the provided file path -// and returns all the modules weighted operations -func SimulationOperations(app runtime.AppSimI, cdc codec.Codec, config simtypes.Config, txConfig client.TxConfig) []simtypes.WeightedOperation { - signingCtx := cdc.InterfaceRegistry().SigningContext() - simState := module.SimulationState{ - AppParams: make(simtypes.AppParams), - Cdc: cdc, - AddressCodec: signingCtx.AddressCodec(), - ValidatorCodec: signingCtx.ValidatorAddressCodec(), - TxConfig: txConfig, - BondDenom: sdk.DefaultBondDenom, - } - - if config.ParamsFile != "" { - bz, err := os.ReadFile(config.ParamsFile) - if err != nil { - panic(err) - } - - err = json.Unmarshal(bz, &simState.AppParams) - if err != nil { - panic(err) - } - } - - simState.LegacyProposalContents = app.SimulationManager().GetProposalContents(simState) //nolint:staticcheck // we're testing the old way here - simState.ProposalMsgs = app.SimulationManager().GetProposalMsgs(simState) - return app.SimulationManager().WeightedOperations(simState) -} - // CheckExportSimulation exports the app state and simulation parameters to JSON // if the export paths are defined. func CheckExportSimulation(app runtime.AppSimI, config simtypes.Config, params simtypes.Params) error { @@ -115,10 +50,10 @@ type DBStatsInterface interface { } // PrintStats prints the corresponding statistics from the app DB. -func PrintStats(db DBStatsInterface) { - fmt.Println("\nLevelDB Stats") - fmt.Println(db.Stats()["leveldb.stats"]) - fmt.Println("LevelDB cached block size", db.Stats()["leveldb.cachedblock"]) +func PrintStats(db DBStatsInterface, logLine func(args ...any)) { + logLine("\nLevelDB Stats") + logLine(db.Stats()["leveldb.stats"]) + logLine("LevelDB cached block size", db.Stats()["leveldb.cachedblock"]) } // GetSimulationLog unmarshals the KVPair's Value to the corresponding type based on the diff --git a/testutil/sims/simulation_helpers_test.go b/testutil/sims/simulation_helpers_test.go index 034b7e4346fd..a982c7ffafd4 100644 --- a/testutil/sims/simulation_helpers_test.go +++ b/testutil/sims/simulation_helpers_test.go @@ -51,7 +51,6 @@ func TestGetSimulationLog(t *testing.T) { } for _, tt := range tests { - tt := tt t.Run(tt.store, func(t *testing.T) { require.Equal(t, tt.expectedLog, GetSimulationLog(tt.store, decoders, tt.kvPairs, tt.kvPairs), tt.store) }) diff --git a/testutil/sims/state_helpers.go b/testutil/sims/state_helpers.go index 684ef474d724..76d06b8959d6 100644 --- a/testutil/sims/state_helpers.go +++ b/testutil/sims/state_helpers.go @@ -2,6 +2,7 @@ package sims import ( "bufio" + "bytes" "encoding/json" "errors" "io" @@ -36,41 +37,11 @@ const ( ) // AppStateFn returns the initial application state using a genesis or the simulation parameters. -// It calls appStateFnWithExtendedCb with nil rawStateCb. func AppStateFn( - cdc codec.JSONCodec, - addresCodec, validatorCodec address.Codec, - simManager *module.SimulationManager, - genesisState map[string]json.RawMessage, -) simtypes.AppStateFn { - return appStateFnWithExtendedCb(cdc, addresCodec, validatorCodec, 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, - addresCodec, validatorCodec address.Codec, - simManager *module.SimulationManager, - genesisState map[string]json.RawMessage, - rawStateCb func(rawState map[string]json.RawMessage), -) simtypes.AppStateFn { - return appStateFnWithExtendedCbs(cdc, addresCodec, validatorCodec, 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. -// 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, addressCodec, validatorCodec address.Codec, - simManager *module.SimulationManager, + modules []module.AppModuleSimulation, 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, @@ -111,11 +82,11 @@ func appStateFnWithExtendedCbs( if err != nil { panic(err) } - appState, simAccs = AppStateRandomizedFn(simManager, r, cdc, accs, genesisTimestamp, appParams, genesisState, addressCodec, validatorCodec) + appState, simAccs = AppStateRandomizedFn(modules, r, cdc, accs, genesisTimestamp, appParams, genesisState, addressCodec, validatorCodec) default: appParams := make(simtypes.AppParams) - appState, simAccs = AppStateRandomizedFn(simManager, r, cdc, accs, genesisTimestamp, appParams, genesisState, addressCodec, validatorCodec) + appState, simAccs = AppStateRandomizedFn(modules, r, cdc, accs, genesisTimestamp, appParams, genesisState, addressCodec, validatorCodec) } rawState := make(map[string]json.RawMessage) @@ -172,17 +143,9 @@ func appStateFnWithExtendedCbs( stakingtypes.ModuleName: stakingState, testutil.BankModuleName: 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) if err != nil { @@ -195,7 +158,7 @@ func appStateFnWithExtendedCbs( // AppStateRandomizedFn creates calls each module's GenesisState generator function // and creates the simulation params func AppStateRandomizedFn( - simManager *module.SimulationManager, + modules []module.AppModuleSimulation, r *rand.Rand, cdc codec.JSONCodec, accs []simtypes.Account, @@ -237,8 +200,7 @@ func AppStateRandomizedFn( BondDenom: sdk.DefaultBondDenom, GenTimestamp: genesisTimestamp, } - - simManager.GenerateGenesisStates(simState) + generateGenesisStates(modules, simState) appState, err := json.Marshal(genesisState) if err != nil { @@ -250,31 +212,38 @@ func AppStateRandomizedFn( // AppStateFromGenesisFileFn util function to generate the genesis AppState // from a genesis.json file. -func AppStateFromGenesisFileFn(r io.Reader, cdc codec.JSONCodec, genesisFile string) (genutiltypes.AppGenesis, []simtypes.Account, error) { +func AppStateFromGenesisFileFn(_ io.Reader, cdc codec.JSONCodec, genesisFile string) (genutiltypes.AppGenesis, []simtypes.Account, error) { file, err := os.Open(filepath.Clean(genesisFile)) if err != nil { panic(err) } + defer file.Close() genesis, err := genutiltypes.AppGenesisFromReader(bufio.NewReader(file)) if err != nil { - return *genesis, nil, err + return genutiltypes.AppGenesis{}, nil, err } - if err := file.Close(); err != nil { - return *genesis, nil, err + appStateJSON := genesis.AppState + newAccs, err := AccountsFromAppState(cdc, appStateJSON) + if err != nil { + panic(err) } + return *genesis, newAccs, nil +} + +func AccountsFromAppState(cdc codec.JSONCodec, appStateJSON json.RawMessage) ([]simtypes.Account, error) { var appState map[string]json.RawMessage - if err = json.Unmarshal(genesis.AppState, &appState); err != nil { - return *genesis, nil, err + if err := json.Unmarshal(appStateJSON, &appState); err != nil { + return nil, err } var authGenesis authtypes.GenesisState if appState[testutil.AuthModuleName] != nil { cdc.MustUnmarshalJSON(appState[testutil.AuthModuleName], &authGenesis) } - + r := bufio.NewReader(bytes.NewReader(appStateJSON)) // any deterministic source newAccs := make([]simtypes.Account, len(authGenesis.Accounts)) for i, acc := range authGenesis.Accounts { // Pick a random private key, since we don't know the actual key @@ -282,20 +251,25 @@ func AppStateFromGenesisFileFn(r io.Reader, cdc codec.JSONCodec, genesisFile str // and these keys are never actually used to sign by mock CometBFT. privkeySeed := make([]byte, 15) if _, err := r.Read(privkeySeed); err != nil { - panic(err) + return nil, err } privKey := secp256k1.GenPrivKeyFromSecret(privkeySeed) a, ok := acc.GetCachedValue().(sdk.AccountI) if !ok { - return *genesis, nil, errors.New("expected account") + return nil, errors.New("expected account") } // create simulator accounts simAcc := simtypes.Account{PrivKey: privKey, PubKey: privKey.PubKey(), Address: a.GetAddress(), ConsKey: ed25519.GenPrivKeyFromSecret(privkeySeed)} newAccs[i] = simAcc } + return newAccs, nil +} - return *genesis, newAccs, nil +func generateGenesisStates(modules []module.AppModuleSimulation, simState *module.SimulationState) { + for _, m := range modules { + m.GenerateGenesisState(simState) + } } diff --git a/testutil/types.go b/testutil/types.go index d4db7fadcabd..3c3ff5c73cc4 100644 --- a/testutil/types.go +++ b/testutil/types.go @@ -4,23 +4,24 @@ package testutil // Those constants are defined here to be used in the SDK without importing those modules. const ( - AccountsModuleName = "accounts" - AuthModuleName = "auth" - AuthzModuleName = "authz" - BankModuleName = "bank" - CircuitModuleName = "circuit" - DistributionModuleName = "distribution" - EvidenceModuleName = "evidence" - FeegrantModuleName = "feegrant" - GovModuleName = "gov" - GroupModuleName = "group" - MintModuleName = "mint" - NFTModuleName = "nft" - ParamsModuleName = "params" - ProtocolPoolModuleName = "protocolpool" - SlashingModuleName = "slashing" - StakingModuleName = "staking" - TxModuleName = "tx" - UpgradeModuleName = "upgrade" - EpochsModuleName = "epochs" + AccountsModuleName = "accounts" + AuthModuleName = "auth" + AuthzModuleName = "authz" + BankModuleName = "bank" + CircuitModuleName = "circuit" + DistributionModuleName = "distribution" + EvidenceModuleName = "evidence" + FeegrantModuleName = "feegrant" + GovModuleName = "gov" + GroupModuleName = "group" + MintModuleName = "mint" + NFTModuleName = "nft" + ParamsModuleName = "params" + ProtocolPoolModuleName = "protocolpool" + SlashingModuleName = "slashing" + StakingModuleName = "staking" + AuthTxConfigDepinjectModuleName = "tx" + UpgradeModuleName = "upgrade" + EpochsModuleName = "epochs" + ValidateModuleName = "validate" ) diff --git a/testutils/sims/runner.go b/testutils/sims/runner.go deleted file mode 100644 index e30a252c0d29..000000000000 --- a/testutils/sims/runner.go +++ /dev/null @@ -1,251 +0,0 @@ -package sims - -import ( - "fmt" - "io" - "os" - "path/filepath" - "testing" - - dbm "github.com/cosmos/cosmos-db" - "github.com/stretchr/testify/require" - - corestore "cosmossdk.io/core/store" - "cosmossdk.io/log" - - "github.com/cosmos/cosmos-sdk/baseapp" - "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/client/flags" - "github.com/cosmos/cosmos-sdk/codec" - "github.com/cosmos/cosmos-sdk/runtime" - "github.com/cosmos/cosmos-sdk/server" - servertypes "github.com/cosmos/cosmos-sdk/server/types" - simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" - simtypes "github.com/cosmos/cosmos-sdk/types/simulation" - "github.com/cosmos/cosmos-sdk/x/simulation" - "github.com/cosmos/cosmos-sdk/x/simulation/client/cli" -) - -const SimAppChainID = "simulation-app" - -// this list of seeds was imported from the original simulation runner: https://github.com/cosmos/tools/blob/v1.0.0/cmd/runsim/main.go#L32 -var defaultSeeds = []int64{ - 1, 2, 4, 7, - 32, 123, 124, 582, 1893, 2989, - 3012, 4728, 37827, 981928, 87821, 891823782, - 989182, 89182391, 11, 22, 44, 77, 99, 2020, - 3232, 123123, 124124, 582582, 18931893, - 29892989, 30123012, 47284728, 7601778, 8090485, - 977367484, 491163361, 424254581, 673398983, -} - -type SimStateFactory struct { - Codec codec.Codec - AppStateFn simtypes.AppStateFn - BlockedAddr map[string]bool -} - -// SimulationApp abstract app that is used by sims -type SimulationApp interface { - runtime.AppSimI - SetNotSigverifyTx() - GetBaseApp() *baseapp.BaseApp - TxConfig() client.TxConfig - Close() error -} - -// Run is a helper function that runs a simulation test with the given parameters. -// It calls the RunWithSeeds function with the default seeds and parameters. -// -// This is the entrypoint to run simulation tests that used to run with the runsim binary. -func Run[T SimulationApp]( - t *testing.T, - appFactory func( - logger log.Logger, - db corestore.KVStoreWithBatch, - traceStore io.Writer, - loadLatest bool, - appOpts servertypes.AppOptions, - baseAppOptions ...func(*baseapp.BaseApp), - ) T, - setupStateFactory func(app T) SimStateFactory, - postRunActions ...func(t *testing.T, app TestInstance[T]), -) { - t.Helper() - RunWithSeeds(t, appFactory, setupStateFactory, defaultSeeds, nil, postRunActions...) -} - -// RunWithSeeds is a helper function that runs a simulation test with the given parameters. -// It iterates over the provided seeds and runs the simulation test for each seed in parallel. -// -// It sets up the environment, creates an instance of the simulation app, -// calls the simulation.SimulateFromSeed function to run the simulation, and performs post-run actions for each seed. -// The execution is deterministic and can be used for fuzz tests as well. -// -// The system under test is isolated for each run but unlike the old runsim command, there is no Process separation. -// This means, global caches may be reused for example. This implementation build upon the vanialla Go stdlib test framework. -func RunWithSeeds[T SimulationApp]( - t *testing.T, - appFactory func( - logger log.Logger, - db corestore.KVStoreWithBatch, - traceStore io.Writer, - loadLatest bool, - appOpts servertypes.AppOptions, - baseAppOptions ...func(*baseapp.BaseApp), - ) T, - setupStateFactory func(app T) SimStateFactory, - seeds []int64, - fuzzSeed []byte, - postRunActions ...func(t *testing.T, app TestInstance[T]), -) { - t.Helper() - cfg := cli.NewConfigFromFlags() - cfg.ChainID = SimAppChainID - for i := range seeds { - seed := seeds[i] - t.Run(fmt.Sprintf("seed: %d", seed), func(t *testing.T) { - t.Parallel() - // setup environment - tCfg := cfg.With(t, seed, fuzzSeed) - testInstance := NewSimulationAppInstance(t, tCfg, appFactory) - var runLogger log.Logger - if cli.FlagVerboseValue { - runLogger = log.NewTestLogger(t) - } else { - runLogger = log.NewTestLoggerInfo(t) - } - runLogger = runLogger.With("seed", tCfg.Seed) - app := testInstance.App - stateFactory := setupStateFactory(app) - simParams, err := simulation.SimulateFromSeedX( - t, - runLogger, - WriteToDebugLog(runLogger), - app.GetBaseApp(), - stateFactory.AppStateFn, - simtypes.RandomAccounts, // Replace with own random account function if using keys other than secp256k1 - simtestutil.SimulationOperations(app, stateFactory.Codec, tCfg, app.TxConfig()), - stateFactory.BlockedAddr, - tCfg, - stateFactory.Codec, - app.TxConfig().SigningContext().AddressCodec(), - testInstance.ExecLogWriter, - ) - require.NoError(t, err) - err = simtestutil.CheckExportSimulation(app, tCfg, simParams) - require.NoError(t, err) - if tCfg.Commit { - db, ok := testInstance.DB.(simtestutil.DBStatsInterface) - if ok { - simtestutil.PrintStats(db) - } - } - for _, step := range postRunActions { - step(t, testInstance) - } - require.NoError(t, app.Close()) - }) - } -} - -// TestInstance is a generic type that represents an instance of a SimulationApp used for testing simulations. -// It contains the following fields: -// - App: The instance of the SimulationApp under test. -// - DB: The LevelDB database for the simulation app. -// - WorkDir: The temporary working directory for the simulation app. -// - Cfg: The configuration flags for the simulator. -// - AppLogger: The logger used for logging in the app during the simulation, with seed value attached. -// - ExecLogWriter: Captures block and operation data coming from the simulation -type TestInstance[T SimulationApp] struct { - App T - DB corestore.KVStoreWithBatch - WorkDir string - Cfg simtypes.Config - AppLogger log.Logger - ExecLogWriter simulation.LogWriter -} - -// NewSimulationAppInstance initializes and returns a TestInstance of a SimulationApp. -// The function takes a testing.T instance, a simtypes.Config instance, and an appFactory function as parameters. -// It creates a temporary working directory and a LevelDB database for the simulation app. -// The function then initializes a logger based on the verbosity flag and sets the logger's seed to the test configuration's seed. -// The database is closed and cleaned up on test completion. -func NewSimulationAppInstance[T SimulationApp]( - t *testing.T, - tCfg simtypes.Config, - appFactory func(logger log.Logger, db corestore.KVStoreWithBatch, traceStore io.Writer, loadLatest bool, appOpts servertypes.AppOptions, baseAppOptions ...func(*baseapp.BaseApp)) T, -) TestInstance[T] { - t.Helper() - workDir := t.TempDir() - require.NoError(t, os.Mkdir(filepath.Join(workDir, "data"), 0o755)) - - dbDir := filepath.Join(workDir, "leveldb-app-sim") - var logger log.Logger - if cli.FlagVerboseValue { - logger = log.NewTestLogger(t) - } else { - logger = log.NewTestLoggerError(t) - } - logger = logger.With("seed", tCfg.Seed) - - db, err := dbm.NewDB("Simulation", dbm.BackendType(tCfg.DBBackend), dbDir) - require.NoError(t, err) - t.Cleanup(func() { - _ = db.Close() // ensure db is closed - }) - appOptions := make(simtestutil.AppOptionsMap) - appOptions[flags.FlagHome] = workDir - appOptions[server.FlagInvCheckPeriod] = cli.FlagPeriodValue - - app := appFactory(logger, db, nil, true, appOptions, baseapp.SetChainID(SimAppChainID)) - if !cli.FlagSigverifyTxValue { - app.SetNotSigverifyTx() - } - return TestInstance[T]{ - App: app, - DB: db, - WorkDir: workDir, - Cfg: tCfg, - AppLogger: logger, - ExecLogWriter: &simulation.StandardLogWriter{Seed: tCfg.Seed}, - } -} - -var _ io.Writer = writerFn(nil) - -type writerFn func(p []byte) (n int, err error) - -func (w writerFn) Write(p []byte) (n int, err error) { - return w(p) -} - -// WriteToDebugLog is an adapter to io.Writer interface -func WriteToDebugLog(logger log.Logger) io.Writer { - return writerFn(func(p []byte) (n int, err error) { - logger.Debug(string(p)) - return len(p), nil - }) -} - -// AppOptionsFn is an adapter to the single method AppOptions interface -type AppOptionsFn func(string) any - -func (f AppOptionsFn) Get(k string) any { - return f(k) -} - -func (f AppOptionsFn) GetString(k string) string { - str, ok := f(k).(string) - if !ok { - return "" - } - - return str -} - -// FauxMerkleModeOpt returns a BaseApp option to use a dbStoreAdapter instead of -// an IAVLStore for faster simulation speed. -func FauxMerkleModeOpt(bapp *baseapp.BaseApp) { - bapp.SetFauxMerkleMode() -} diff --git a/tools/confix/Makefile b/tools/confix/Makefile index 417b7a7c4933..5c29441e29de 100644 --- a/tools/confix/Makefile +++ b/tools/confix/Makefile @@ -4,9 +4,11 @@ all: confix condiff test confix: go build -mod=readonly ./cmd/confix + @echo "confix binary has been successfully built in tools/confix/confix" condiff: go build -mod=readonly ./cmd/condiff + @echo "condiff binary has been successfully built in tools/confix/condiff" test: go test -mod=readonly -race ./... diff --git a/tools/confix/README.md b/tools/confix/README.md index 64b2f49b3dc7..00851ede1923 100644 --- a/tools/confix/README.md +++ b/tools/confix/README.md @@ -23,7 +23,7 @@ import "cosmossdk.io/tools/confix/cmd" Find the following line: ```go -initRootCmd(rootCmd, encodingConfig) +initRootCmd(rootCmd, moduleManager) ``` After that line, add the following: @@ -39,10 +39,10 @@ An implementation example can be found in `simapp`. The command will be available as `simd config`. -```tip +:::tip Using confix directly in the application can have less features than using it standalone. This is because confix is versioned with the SDK, while `latest` is the standalone version. -``` +::: ### Using Confix Standalone @@ -138,7 +138,7 @@ confix view ~/.simapp/config/client.toml # views the current app client conf ### Maintainer -At each SDK modification of the default configuration, add the default SDK config under `data/v0.XX-app.toml`. +At each SDK modification of the default configuration, add the default SDK config under `data/vXX-app.toml`. This allows users to use the tool standalone. ### Compatibility @@ -149,7 +149,8 @@ The recommended standalone version is `latest`, which is using the latest develo | ----------- | -------------- | | v0.50 | v0.1.x | | v0.52 | v0.2.x | +| v2 | v0.2.x | ## Credits -This project is based on the [CometBFT RFC 019](https://github.com/cometbft/cometbft/blob/5013bc3f4a6d64dcc2bf02ccc002ebc9881c62e4/docs/rfc/rfc-019-config-version.md) and their own implementation of [confix](https://github.com/cometbft/cometbft/blob/v0.36.x/scripts/confix/confix.go). +This project is based on the [CometBFT RFC 019](https://github.com/cometbft/cometbft/blob/5013bc3f4a6d64dcc2bf02ccc002ebc9881c62e4/docs/rfc/rfc-019-config-version.md) and their never released own implementation of [confix](https://github.com/cometbft/cometbft/blob/v0.36.x/scripts/confix/confix.go). diff --git a/tools/confix/data/v0.52-app.toml b/tools/confix/data/v0.52-app.toml index d6e3cf95ab01..f97f48044502 100644 --- a/tools/confix/data/v0.52-app.toml +++ b/tools/confix/data/v0.52-app.toml @@ -66,7 +66,7 @@ index-events = [] # IavlCacheSize set the size of the iavl tree cache (in number of nodes). iavl-cache-size = 781250 -# IAVLDisableFastNode enables or disables the fast node feature of IAVL. +# IAVLDisableFastNode enables or disables the fast node feature of IAVL. # Default is false. iavl-disable-fastnode = false @@ -223,9 +223,3 @@ stop-node-on-err = true # Note, this configuration only applies to SDK built-in app-side mempool # implementations. max-txs = -1 - -[custom] - -# That field will be parsed by server.InterceptConfigsPreRunHandler and held by viper. -# Do not forget to add quotes around the value if it is a string. -custom-field = "anything" diff --git a/tools/confix/data/v2-app.toml b/tools/confix/data/v2-app.toml index 8f7f7f9940d2..c4f19348ce52 100644 --- a/tools/confix/data/v2-app.toml +++ b/tools/confix/data/v2-app.toml @@ -16,6 +16,11 @@ trace = false # standalone starts the application without the CometBFT node. The node should be started separately. standalone = false +# mempool defines the configuration for the SDK built-in app-side mempool implementations. +[comet.mempool] +# max-txs defines the maximum number of transactions that can be in the mempool. A value of 0 indicates an unbounded mempool, a negative value disables the app-side mempool. +max-txs = -1 + [grpc] # Enable defines if the gRPC server should be enabled. enable = true @@ -37,27 +42,53 @@ minimum-gas-prices = '0stake' app-db-backend = 'goleveldb' [store.options] -# State storage database type. Currently we support: 0 for SQLite, 1 for Pebble -ss-type = 0 -# State commitment database type. Currently we support:0 for iavl, 1 for iavl v2 -sc-type = 0 +# SState storage database type. Currently we support: "sqlite", "pebble" and "rocksdb" +ss-type = 'sqlite' +# State commitment database type. Currently we support: "iavl" and "iavl-v2" +sc-type = 'iavl' # Pruning options for state storage [store.options.ss-pruning-option] # Number of recent heights to keep on disk. keep-recent = 2 # Height interval at which pruned heights are removed from disk. -interval = 1 +interval = 100 # Pruning options for state commitment [store.options.sc-pruning-option] # Number of recent heights to keep on disk. keep-recent = 2 # Height interval at which pruned heights are removed from disk. -interval = 1 +interval = 100 [store.options.iavl-config] # CacheSize set the size of the iavl tree cache. cache-size = 100000 # If true, the tree will work like no fast storage and always not upgrade fast storage. skip-fast-storage-upgrade = true + +[telemetry] +# Enable enables the application telemetry functionality. When enabled, an in-memory sink is also enabled by default. Operators may also enabled other sinks such as Prometheus. +enable = true +# Address defines the metrics server address to bind to. +address = 'localhost:1338' +# Prefixed with keys to separate services. +service-name = '' +# Enable prefixing gauge values with hostname. +enable-hostname = false +# Enable adding hostname to labels. +enable-hostname-label = false +# Enable adding service to labels. +enable-service-label = false +# PrometheusRetentionTime, when positive, enables a Prometheus metrics sink. It defines the retention duration in seconds. +prometheus-retention-time = 0 +# GlobalLabels defines a global set of name/value label tuples applied to all metrics emitted using the wrapper functions defined in telemetry package. +# Example: +# [["chain_id", "cosmoshub-1"]] +global-labels = [] +# MetricsSink defines the type of metrics backend to use. Default is in memory +metrics-sink = '' +# StatsdAddr defines the address of a statsd server to send metrics to. Only utilized if MetricsSink is set to "statsd" or "dogstatsd". +stats-addr = '' +# DatadogHostname defines the hostname to use when emitting metrics to Datadog. Only utilized if MetricsSink is set to "dogstatsd". +data-dog-hostname = '' diff --git a/tools/confix/go.mod b/tools/confix/go.mod index 61a003f48483..e6800c66e46b 100644 --- a/tools/confix/go.mod +++ b/tools/confix/go.mod @@ -3,7 +3,7 @@ module cosmossdk.io/tools/confix go 1.23 require ( - github.com/cosmos/cosmos-sdk v0.50.9 + github.com/cosmos/cosmos-sdk v0.50.10 github.com/creachadair/atomicfile v0.3.5 github.com/creachadair/tomledit v0.0.26 github.com/pelletier/go-toml/v2 v2.2.3 @@ -13,15 +13,15 @@ require ( ) require ( - cosmossdk.io/api v0.7.5 // indirect + cosmossdk.io/api v0.7.6 // indirect cosmossdk.io/collections v0.4.0 // indirect cosmossdk.io/core v0.11.1 // indirect cosmossdk.io/depinject v1.0.0 // indirect cosmossdk.io/errors v1.0.1 // indirect cosmossdk.io/log v1.4.1 // indirect cosmossdk.io/math v1.3.0 // indirect - cosmossdk.io/store v1.1.0 // indirect - cosmossdk.io/x/tx v0.13.4 // indirect + cosmossdk.io/store v1.1.1 // indirect + cosmossdk.io/x/tx v0.13.5 // indirect filippo.io/edwards25519 v1.1.0 // indirect github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect github.com/99designs/keyring v1.2.1 // indirect @@ -29,24 +29,25 @@ require ( github.com/DataDog/zstd v1.5.5 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bgentry/speakeasy v0.2.0 // indirect - github.com/btcsuite/btcd/btcec/v2 v2.3.3 // indirect + github.com/btcsuite/btcd/btcec/v2 v2.3.4 // indirect github.com/cenkalti/backoff/v4 v4.1.3 // indirect github.com/cespare/xxhash v1.1.0 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect - github.com/cockroachdb/errors v1.11.1 // indirect + github.com/cockroachdb/errors v1.11.3 // indirect + github.com/cockroachdb/fifo v0.0.0-20240606204812-0bbfbd93a7ce // indirect github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect - github.com/cockroachdb/pebble v1.1.0 // indirect + github.com/cockroachdb/pebble v1.1.1 // indirect github.com/cockroachdb/redact v1.1.5 // indirect github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect - github.com/cometbft/cometbft v0.38.10 // indirect - github.com/cometbft/cometbft-db v0.9.1 // indirect + github.com/cometbft/cometbft v0.38.12 // indirect + github.com/cometbft/cometbft-db v0.11.0 // indirect github.com/cosmos/btcutil v1.0.5 // indirect github.com/cosmos/cosmos-db v1.0.3-0.20240829004618-717cba019b33 // indirect github.com/cosmos/cosmos-proto v1.0.0-beta.5 // indirect github.com/cosmos/go-bip39 v1.0.0 // indirect github.com/cosmos/gogogateway v1.2.0 // indirect github.com/cosmos/gogoproto v1.7.0 // indirect - github.com/cosmos/iavl v1.1.4 // indirect + github.com/cosmos/iavl v1.2.0 // indirect github.com/cosmos/ics23/go v0.11.0 // indirect github.com/cosmos/ledger-cosmos-go v0.13.3 // indirect github.com/danieljoos/wincred v1.1.2 // indirect @@ -69,7 +70,7 @@ require ( github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect github.com/gogo/googleapis v1.4.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang/glog v1.2.1 // indirect + github.com/golang/glog v1.2.2 // indirect github.com/golang/mock v1.6.0 // indirect github.com/golang/protobuf v1.5.4 // indirect github.com/golang/snappy v0.0.4 // indirect @@ -78,7 +79,7 @@ require ( github.com/google/orderedcode v0.0.1 // indirect github.com/gorilla/handlers v1.5.2 // indirect github.com/gorilla/mux v1.8.1 // indirect - github.com/gorilla/websocket v1.5.0 // indirect + github.com/gorilla/websocket v1.5.3 // indirect github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 // indirect github.com/grpc-ecosystem/grpc-gateway v1.16.0 // indirect github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c // indirect @@ -91,7 +92,7 @@ require ( github.com/hashicorp/hcl v1.0.0 // indirect github.com/hashicorp/yamux v0.1.1 // indirect github.com/hdevalence/ed25519consensus v0.2.0 // indirect - github.com/huandu/skiplist v1.2.0 // indirect + github.com/huandu/skiplist v1.2.1 // indirect github.com/iancoleman/strcase v0.3.0 // indirect github.com/improbable-eng/grpc-web v0.15.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect @@ -114,13 +115,13 @@ require ( github.com/petermattis/goid v0.0.0-20240327183114-c42a807a84ba // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/client_golang v1.20.3 // indirect + github.com/prometheus/client_golang v1.20.4 // indirect github.com/prometheus/client_model v0.6.1 // indirect - github.com/prometheus/common v0.59.1 // indirect + github.com/prometheus/common v0.60.0 // indirect github.com/prometheus/procfs v0.15.1 // indirect github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect github.com/rogpeppe/go-internal v1.12.0 // indirect - github.com/rs/cors v1.11.0 // indirect + github.com/rs/cors v1.11.1 // indirect github.com/rs/zerolog v1.33.0 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect @@ -136,7 +137,7 @@ require ( github.com/tidwall/btree v1.7.0 // indirect github.com/zondax/hid v0.9.2 // indirect github.com/zondax/ledger-go v0.14.3 // indirect - go.etcd.io/bbolt v1.3.8 // indirect + go.etcd.io/bbolt v1.3.10 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/crypto v0.27.0 // indirect golang.org/x/exp v0.0.0-20240531132922-fd00a4e0eefc // indirect @@ -146,9 +147,9 @@ require ( golang.org/x/term v0.24.0 // indirect golang.org/x/text v0.18.0 // indirect google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect - google.golang.org/grpc v1.66.2 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f // indirect + google.golang.org/grpc v1.67.1 // indirect google.golang.org/protobuf v1.34.2 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/tools/confix/go.sum b/tools/confix/go.sum index 126663680c74..32242dcba2a9 100644 --- a/tools/confix/go.sum +++ b/tools/confix/go.sum @@ -1,7 +1,7 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cosmossdk.io/api v0.7.5 h1:eMPTReoNmGUm8DeiQL9DyM8sYDjEhWzL1+nLbI9DqtQ= -cosmossdk.io/api v0.7.5/go.mod h1:IcxpYS5fMemZGqyYtErK7OqvdM0C8kdW3dq8Q/XIG38= +cosmossdk.io/api v0.7.6 h1:PC20PcXy1xYKH2KU4RMurVoFjjKkCgYRbVAD4PdqUuY= +cosmossdk.io/api v0.7.6/go.mod h1:IcxpYS5fMemZGqyYtErK7OqvdM0C8kdW3dq8Q/XIG38= cosmossdk.io/collections v0.4.0 h1:PFmwj2W8szgpD5nOd8GWH6AbYNi1f2J6akWXJ7P5t9s= cosmossdk.io/collections v0.4.0/go.mod h1:oa5lUING2dP+gdDquow+QjlF45eL1t4TJDypgGd+tv0= cosmossdk.io/core v0.11.1 h1:h9WfBey7NAiFfIcUhDVNS503I2P2HdZLebJlUIs8LPA= @@ -14,10 +14,10 @@ cosmossdk.io/log v1.4.1 h1:wKdjfDRbDyZRuWa8M+9nuvpVYxrEOwbD/CA8hvhU8QM= cosmossdk.io/log v1.4.1/go.mod h1:k08v0Pyq+gCP6phvdI6RCGhLf/r425UT6Rk/m+o74rU= cosmossdk.io/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE= cosmossdk.io/math v1.3.0/go.mod h1:vnRTxewy+M7BtXBNFybkuhSH4WfedVAAnERHgVFhp3k= -cosmossdk.io/store v1.1.0 h1:LnKwgYMc9BInn9PhpTFEQVbL9UK475G2H911CGGnWHk= -cosmossdk.io/store v1.1.0/go.mod h1:oZfW/4Fc/zYqu3JmQcQdUJ3fqu5vnYTn3LZFFy8P8ng= -cosmossdk.io/x/tx v0.13.4 h1:Eg0PbJgeO0gM8p5wx6xa0fKR7hIV6+8lC56UrsvSo0Y= -cosmossdk.io/x/tx v0.13.4/go.mod h1:BkFqrnGGgW50Y6cwTy+JvgAhiffbGEKW6KF9ufcDpvk= +cosmossdk.io/store v1.1.1 h1:NA3PioJtWDVU7cHHeyvdva5J/ggyLDkyH0hGHl2804Y= +cosmossdk.io/store v1.1.1/go.mod h1:8DwVTz83/2PSI366FERGbWSH7hL6sB7HbYp8bqksNwM= +cosmossdk.io/x/tx v0.13.5 h1:FdnU+MdmFWn1pTsbfU0OCf2u6mJ8cqc1H4OMG418MLw= +cosmossdk.io/x/tx v0.13.5/go.mod h1:V6DImnwJMTq5qFjeGWpXNiT/fjgE4HtmclRmTqRVM3w= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= @@ -73,10 +73,10 @@ github.com/bgentry/speakeasy v0.2.0 h1:tgObeVOf8WAvtuAX6DhJ4xks4CFNwPDZiqzGqIHE5 github.com/bgentry/speakeasy v0.2.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bits-and-blooms/bitset v1.8.0 h1:FD+XqgOZDUxxZ8hzoBFuV9+cGWY9CslN6d5MS5JVb4c= github.com/bits-and-blooms/bitset v1.8.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= -github.com/btcsuite/btcd/btcec/v2 v2.3.3 h1:6+iXlDKE8RMtKsvK0gshlXIuPbyWM/h84Ensb7o3sC0= -github.com/btcsuite/btcd/btcec/v2 v2.3.3/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= -github.com/btcsuite/btcd/btcutil v1.1.3 h1:xfbtw8lwpp0G6NwSHb+UE67ryTFHJAiNuipusjXSohQ= -github.com/btcsuite/btcd/btcutil v1.1.3/go.mod h1:UR7dsSJzJUfMmFiiLlIrMq1lS9jh9EdCV7FStZSnpi0= +github.com/btcsuite/btcd/btcec/v2 v2.3.4 h1:3EJjcN70HCu/mwqlUsGK8GcNVyLVxFDlWurTXGPFfiQ= +github.com/btcsuite/btcd/btcec/v2 v2.3.4/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= +github.com/btcsuite/btcd/btcutil v1.1.6 h1:zFL2+c3Lb9gEgqKNzowKUPQNb8jV7v5Oaodi/AYFd6c= +github.com/btcsuite/btcd/btcutil v1.1.6/go.mod h1:9dFymx8HpuLqBnsPELrImQeTQfKBQqzqGbbV3jK55aE= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/bufbuild/protocompile v0.6.0 h1:Uu7WiSQ6Yj9DbkdnOe7U4mNKp58y9WDMKDn28/ZlunY= @@ -114,21 +114,23 @@ github.com/cockroachdb/apd/v2 v2.0.2/go.mod h1:DDxRlzC2lo3/vSlmSoS7JkqbbrARPuFOG github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= github.com/cockroachdb/datadriven v1.0.3-0.20230413201302-be42291fc80f h1:otljaYPt5hWxV3MUfO5dFPFiOXg9CyG5/kCfayTqsJ4= github.com/cockroachdb/datadriven v1.0.3-0.20230413201302-be42291fc80f/go.mod h1:a9RdTaap04u637JoCzcUoIcDmvwSUtcUFtT/C3kJlTU= -github.com/cockroachdb/errors v1.11.1 h1:xSEW75zKaKCWzR3OfxXUxgrk/NtT4G1MiOv5lWZazG8= -github.com/cockroachdb/errors v1.11.1/go.mod h1:8MUxA3Gi6b25tYlFEBGLf+D8aISL+M4MIpiWMSNRfxw= +github.com/cockroachdb/errors v1.11.3 h1:5bA+k2Y6r+oz/6Z/RFlNeVCesGARKuC6YymtcDrbC/I= +github.com/cockroachdb/errors v1.11.3/go.mod h1:m4UIW4CDjx+R5cybPsNrRbreomiFqt8o1h1wUVazSd8= +github.com/cockroachdb/fifo v0.0.0-20240606204812-0bbfbd93a7ce h1:giXvy4KSc/6g/esnpM7Geqxka4WSqI1SZc7sMJFd3y4= +github.com/cockroachdb/fifo v0.0.0-20240606204812-0bbfbd93a7ce/go.mod h1:9/y3cnZ5GKakj/H4y9r9GTjCvAFta7KLgSHPJJYc52M= github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b h1:r6VH0faHjZeQy818SGhaone5OnYfxFR/+AzdY3sf5aE= github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs= -github.com/cockroachdb/pebble v1.1.0 h1:pcFh8CdCIt2kmEpK0OIatq67Ln9uGDYY3d5XnE0LJG4= -github.com/cockroachdb/pebble v1.1.0/go.mod h1:sEHm5NOXxyiAoKWhoFxT8xMgd/f3RA6qUqQ1BXKrh2E= +github.com/cockroachdb/pebble v1.1.1 h1:XnKU22oiCLy2Xn8vp1re67cXg4SAasg/WDt1NtcRFaw= +github.com/cockroachdb/pebble v1.1.1/go.mod h1:4exszw1r40423ZsmkG/09AFEG83I0uDgfujJdbL6kYU= github.com/cockroachdb/redact v1.1.5 h1:u1PMllDkdFfPWaNGMyLD1+so+aq3uUItthCFqzwPJ30= github.com/cockroachdb/redact v1.1.5/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg= github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 h1:zuQyyAKVxetITBuuhv3BI9cMrmStnpT18zmgmTxunpo= github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06/go.mod h1:7nc4anLGjupUW/PeY5qiNYsdNXj7zopG+eqsS7To5IQ= github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= -github.com/cometbft/cometbft v0.38.10 h1:2ePuglchT+j0Iao+cfmt/nw5U7K2lnGDzXSUPGVdXaU= -github.com/cometbft/cometbft v0.38.10/go.mod h1:jHPx9vQpWzPHEAiYI/7EDKaB1NXhK6o3SArrrY8ExKc= -github.com/cometbft/cometbft-db v0.9.1 h1:MIhVX5ja5bXNHF8EYrThkG9F7r9kSfv8BX4LWaxWJ4M= -github.com/cometbft/cometbft-db v0.9.1/go.mod h1:iliyWaoV0mRwBJoizElCwwRA9Tf7jZJOURcRZF9m60U= +github.com/cometbft/cometbft v0.38.12 h1:OWsLZN2KcSSFe8bet9xCn07VwhBnavPea3VyPnNq1bg= +github.com/cometbft/cometbft v0.38.12/go.mod h1:GPHp3/pehPqgX1930HmK1BpBLZPxB75v/dZg8Viwy+o= +github.com/cometbft/cometbft-db v0.11.0 h1:M3Lscmpogx5NTbb1EGyGDaFRdsoLWrUWimFEyf7jej8= +github.com/cometbft/cometbft-db v0.11.0/go.mod h1:GDPJAC/iFHNjmZZPN8V8C1yr/eyityhi2W1hz2MGKSc= github.com/containerd/continuity v0.3.0 h1:nisirsYROK15TAMVukJOUyGJjz4BNQJBVsNvAXZJ/eg= github.com/containerd/continuity v0.3.0/go.mod h1:wJEAIwKOm/pBZuBd0JmeTvnLquTB1Ag8espWhkykbPM= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= @@ -143,8 +145,8 @@ github.com/cosmos/cosmos-db v1.0.3-0.20240829004618-717cba019b33 h1:NnqmEOIzUPaz github.com/cosmos/cosmos-db v1.0.3-0.20240829004618-717cba019b33/go.mod h1:Z8IXcFJ9PqKK6BIsVOB3QXtkKoqUOp1vRvPT39kOXEA= github.com/cosmos/cosmos-proto v1.0.0-beta.5 h1:eNcayDLpip+zVLRLYafhzLvQlSmyab+RC5W7ZfmxJLA= github.com/cosmos/cosmos-proto v1.0.0-beta.5/go.mod h1:hQGLpiIUloJBMdQMMWb/4wRApmI9hjHH05nefC0Ojec= -github.com/cosmos/cosmos-sdk v0.50.9 h1:gt2usjz0H0qW6KwAxWw7ZJ3XU8uDwmhN+hYG3nTLeSg= -github.com/cosmos/cosmos-sdk v0.50.9/go.mod h1:TMH6wpoYBcg7Cp5BEg8fneLr+8XloNQkf2MRNF9V6JE= +github.com/cosmos/cosmos-sdk v0.50.10 h1:zXfeu/z653tWZARr/jESzAEiCUYjgJwwG4ytnYWMoDM= +github.com/cosmos/cosmos-sdk v0.50.10/go.mod h1:6Eesrx3ZE7vxBZWpK++30H+Uc7Q4ahQWCL7JKU/LEdU= 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/gogogateway v1.2.0 h1:Ae/OivNhp8DqBi/sh2A8a1D0y638GpL3tkmLQAiKxTE= @@ -152,8 +154,8 @@ github.com/cosmos/gogogateway v1.2.0/go.mod h1:iQpLkGWxYcnCdz5iAdLcRBSw3h7NXeOkZ github.com/cosmos/gogoproto v1.4.2/go.mod h1:cLxOsn1ljAHSV527CHOtaIP91kK6cCrZETRBrkzItWU= github.com/cosmos/gogoproto v1.7.0 h1:79USr0oyXAbxg3rspGh/m4SWNyoz/GLaAh0QlCe2fro= github.com/cosmos/gogoproto v1.7.0/go.mod h1:yWChEv5IUEYURQasfyBW5ffkMHR/90hiHgbNgrtp4j0= -github.com/cosmos/iavl v1.1.4 h1:Z0cVVjeQqOUp78/nWt/uhQy83vYluWlAMGQ4zbH9G34= -github.com/cosmos/iavl v1.1.4/go.mod h1:vCYmRQUJU1wwj0oRD3wMEtOM9sJNDP+GFMaXmIxZ/rU= +github.com/cosmos/iavl v1.2.0 h1:kVxTmjTh4k0Dh1VNL046v6BXqKziqMDzxo93oh3kOfM= +github.com/cosmos/iavl v1.2.0/go.mod h1:HidWWLVAtODJqFD6Hbne2Y0q3SdxByJepHUOeoH4LiI= github.com/cosmos/ics23/go v0.11.0 h1:jk5skjT0TqX5e5QJbEnwXIS2yI2vnmLOgpQPeM5RtnU= github.com/cosmos/ics23/go v0.11.0/go.mod h1:A8OjxPE67hHST4Icw94hOxxFEJMBG031xIGF/JHNIY0= github.com/cosmos/ledger-cosmos-go v0.13.3 h1:7ehuBGuyIytsXbd4MP43mLeoN2LTOEnk5nvue4rK+yM= @@ -290,8 +292,8 @@ github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXP github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/glog v1.2.1 h1:OptwRhECazUx5ix5TTWC3EZhsZEHWcYWY4FQHTIubm4= -github.com/golang/glog v1.2.1/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= +github.com/golang/glog v1.2.2 h1:1+mZ9upx1Dh6FmUTFR1naJ77miKiXgALjWOZ3NVFPmY= +github.com/golang/glog v1.2.2/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= @@ -353,8 +355,8 @@ github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= -github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= +github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-middleware v1.2.2/go.mod h1:EaizFBKfUKtMIF5iaDEhniwNedqGo9FuLFzppDr3uwI= github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 h1:UH//fgunKIs4JdUbpDl1VZCDaL56wXCB/5+wF6uHfaI= @@ -409,8 +411,8 @@ github.com/hdevalence/ed25519consensus v0.2.0/go.mod h1:w3BHWjwJbFU29IRHL1Iqkw3s github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/huandu/go-assert v1.1.5 h1:fjemmA7sSfYHJD7CUqs9qTwwfdNAx7/j2/ZlHXzNB3c= github.com/huandu/go-assert v1.1.5/go.mod h1:yOLvuqZwmcHIC5rIzrBhT7D3Q9c3GFnd0JrPVhn/06U= -github.com/huandu/skiplist v1.2.0 h1:gox56QD77HzSC0w+Ws3MH3iie755GBJU1OER3h5VsYw= -github.com/huandu/skiplist v1.2.0/go.mod h1:7v3iFjLcSAzO4fN5B8dvebvo/qsfumiLiDXMrPiHF9w= +github.com/huandu/skiplist v1.2.1 h1:dTi93MgjwErA/8idWTzIw4Y1kZsMWx35fmI2c8Rij7w= +github.com/huandu/skiplist v1.2.1/go.mod h1:7v3iFjLcSAzO4fN5B8dvebvo/qsfumiLiDXMrPiHF9w= github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI= github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= @@ -600,8 +602,8 @@ 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.20.3 h1:oPksm4K8B+Vt35tUhw6GbSNSgVlVSBH0qELP/7u83l4= -github.com/prometheus/client_golang v1.20.3/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_golang v1.20.4 h1:Tgh3Yr67PaOv/uTqloMsCEdeuFTatm5zIq5+qNN23vI= +github.com/prometheus/client_golang v1.20.4/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -616,8 +618,8 @@ 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.59.1 h1:LXb1quJHWm1P6wq/U824uxYi4Sg0oGvNeUm1z5dJoX0= -github.com/prometheus/common v0.59.1/go.mod h1:GpWM7dewqmVYcd7SmRaiWVe9SSqjf0UrwnYnpEZNuT0= +github.com/prometheus/common v0.60.0 h1:+V9PAREWNvJMAuJ1x1BaWl9dewMW4YrHZQbx0sJNllA= +github.com/prometheus/common v0.60.0/go.mod h1:h0LYf1R1deLSKtD4Vdg8gy4RuOvENW2J/h19V5NADQw= 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= @@ -636,8 +638,8 @@ github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/f github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= -github.com/rs/cors v1.11.0 h1:0B9GE/r9Bc2UxRMMtymBkHTenPkHDv0CW4Y98GBY+po= -github.com/rs/cors v1.11.0/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= +github.com/rs/cors v1.11.1 h1:eU3gRzXLRK57F5rKMGMZURNdIG4EoAmX8k94r9wXWHA= +github.com/rs/cors v1.11.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8= github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= @@ -731,8 +733,8 @@ github.com/zondax/hid v0.9.2/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWp github.com/zondax/ledger-go v0.14.3 h1:wEpJt2CEcBJ428md/5MgSLsXLBos98sBOyxNmCjfUCw= github.com/zondax/ledger-go v0.14.3/go.mod h1:IKKaoxupuB43g4NxeQmbLXv7T9AlQyie1UpHb342ycI= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= -go.etcd.io/bbolt v1.3.8 h1:xs88BrvEv273UsB79e0hcVrlUWmS0a8upikMFhSyAtA= -go.etcd.io/bbolt v1.3.8/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw= +go.etcd.io/bbolt v1.3.10 h1:+BqfJTcCzTItrop8mq/lbzL8wSGtj94UO/3U31shqG0= +go.etcd.io/bbolt v1.3.10/go.mod h1:bK3UQLPJZly7IlNmV7uVHJDxfe5aK9Ll93e/74Y9oEQ= go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= @@ -942,10 +944,10 @@ google.golang.org/genproto v0.0.0-20210126160654-44e461bb6506/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20220314164441-57ef72a4c106/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E= google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de h1:F6qOa9AZTYJXOUEr4jDysRDLrm4PHePlge4v4TGAlxY= google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:VUhTRKeHn9wwcdrk73nvdC9gF178Tzhmt/qyaFcPLSo= -google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 h1:+rdxYoE3E5htTEWIe15GlN6IfvbURM//Jt0mmkmm6ZU= -google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117/go.mod h1:OimBR/bc1wPO9iV4NC2bpyjy3VnAwZh5EBPQdtaE5oo= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:pPJltXNxVzT4pK9yD8vR9X75DaWYYmLGMsEvBfFQZzQ= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= +google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 h1:wKguEg1hsxI2/L3hUYrpo1RVi48K+uTyzKqprwLXsb8= +google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142/go.mod h1:d6be+8HhtEtucleCbxpPW9PA9XwISACu8nvpPqF0BVo= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f h1:cUMEy+8oS78BWIH9OWazBkzbr090Od9tWBNtZHkOhf0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= 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.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= @@ -963,8 +965,8 @@ google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTp google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= -google.golang.org/grpc v1.66.2 h1:3QdXkuq3Bkh7w+ywLdLvM56cmGvQHUMZpiCzt6Rqaoo= -google.golang.org/grpc v1.66.2/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y= +google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E= +google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= 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= diff --git a/tools/confix/migrations.go b/tools/confix/migrations.go index 437c628d7b25..77fc4a671cb4 100644 --- a/tools/confix/migrations.go +++ b/tools/confix/migrations.go @@ -55,6 +55,8 @@ var v2KeyChanges = v2KeyChangesMap{ }, "iavl-cache-size": []string{"store.options.iavl-config.cache-size"}, "iavl-disable-fastnode": []string{"store.options.iavl-config.skip-fast-storage-upgrade"}, + "telemetry.enabled": []string{"telemetry.enable"}, + "mempool.max-txs": []string{"comet.mempool.max-txs"}, // Add other key mappings as needed } @@ -74,7 +76,6 @@ func PlanBuilder(from *tomledit.Document, to, planType string, loadFn loadDestCo diffs := DiffKeys(from, target) for _, diff := range diffs { - diff := diff kv := diff.KV var step transform.Step diff --git a/tools/cosmovisor/CHANGELOG.md b/tools/cosmovisor/CHANGELOG.md index a4c78e469c45..3db3e4ea9954 100644 --- a/tools/cosmovisor/CHANGELOG.md +++ b/tools/cosmovisor/CHANGELOG.md @@ -36,20 +36,28 @@ Ref: https://keepachangelog.com/en/1.0.0/ ## [Unreleased] +### Features + +* [#21972](https://github.com/cosmos/cosmos-sdk/pull/21972) Add `prepare-upgrade` command + ### Improvements * [#21462](https://github.com/cosmos/cosmos-sdk/pull/21462) Pass `stdin` to binary. +### Features + +* [#21932](https://github.com/cosmos/cosmos-sdk/pull/21932) Add `cosmovisor show-upgrade-info` command to display the upgrade-info.json into stdout. + ## v1.6.0 - 2024-08-12 ## Improvements * Bump `cosmossdk.io/x/upgrade` to v0.1.4 (including go-getter vulnerability fix) * [#19995](https://github.com/cosmos/cosmos-sdk/pull/19995): - * `init command` writes the configuration to the config file only at the default path `DAEMON_HOME/cosmovisor/config.toml`. - * Provide `--cosmovisor-config` flag with value as args to provide the path to the configuration file in the `run` command. `run --cosmovisor-config (other cmds with flags) ...`. - * Add `--cosmovisor-config` flag to provide `config.toml` path to the configuration file in root command used by `add-upgrade` and `config` subcommands. - * `config command` now displays the configuration from the config file if it is provided. If the config file is not provided, it will display the configuration from the environment variables. + * `init command` writes the configuration to the config file only at the default path `DAEMON_HOME/cosmovisor/config.toml`. + * Provide `--cosmovisor-config` flag with value as args to provide the path to the configuration file in the `run` command. `run --cosmovisor-config (other cmds with flags) ...`. + * Add `--cosmovisor-config` flag to provide `config.toml` path to the configuration file in root command used by `add-upgrade` and `config` subcommands. + * `config command` now displays the configuration from the config file if it is provided. If the config file is not provided, it will display the configuration from the environment variables. ## Bug Fixes diff --git a/tools/cosmovisor/Makefile b/tools/cosmovisor/Makefile index b5a7be601e9c..94a02976acf3 100644 --- a/tools/cosmovisor/Makefile +++ b/tools/cosmovisor/Makefile @@ -4,6 +4,7 @@ all: cosmovisor test cosmovisor: go build -mod=readonly ./cmd/cosmovisor + @echo "cosmovisor binary has been successfully built in tools/cosmovisor/cosmovisor" test: go test -mod=readonly -race ./... diff --git a/tools/cosmovisor/README.md b/tools/cosmovisor/README.md index db15ab0a5d64..3b5f722c5d1b 100644 --- a/tools/cosmovisor/README.md +++ b/tools/cosmovisor/README.md @@ -7,21 +7,21 @@ sidebar_position: 1 `cosmovisor` is a process manager for Cosmos SDK application binaries that automates application binary switch at chain upgrades. It polls the `upgrade-info.json` file that is created by the x/upgrade module at upgrade height, and then can automatically download the new binary, stop the current binary, switch from the old binary to the new one, and finally restart the node with the new binary. -* [Cosmovisor](#cosmovisor) - * [Design](#design) - * [Contributing](#contributing) - * [Setup](#setup) +* [Design](#design) +* [Contributing](#contributing) +* [Setup](#setup) * [Installation](#installation) * [Command Line Arguments And Environment Variables](#command-line-arguments-and-environment-variables) * [Folder Layout](#folder-layout) - * [Usage](#usage) +* [Usage](#usage) * [Initialization](#initialization) * [Detecting Upgrades](#detecting-upgrades) * [Adding Upgrade Binary](#adding-upgrade-binary) * [Auto-Download](#auto-download) - * [Example: SimApp Upgrade](#example-simapp-upgrade) + * [Preparing for an Upgrade](#preparing-for-an-upgrade) +* [Example: SimApp Upgrade](#example-simapp-upgrade) * [Chain Setup](#chain-setup) - * [Prepare Cosmovisor and Start the Chain](#prepare-cosmovisor-and-start-the-chain) + * [Prepare Cosmovisor and Start the Chain](#prepare-cosmovisor-and-start-the-chain) * [Update App](#update-app) ## Design @@ -263,6 +263,38 @@ The result will look something like the following: `29139e1381b8177aec909fab9a75 You can also use `sha512sum` if you would prefer to use longer hashes, or `md5sum` if you would prefer to use broken hashes. Whichever you choose, make sure to set the hash algorithm properly in the checksum argument to the URL. +### Preparing for an Upgrade + +To prepare for an upgrade, use the `prepare-upgrade` command: + +```shell +cosmovisor prepare-upgrade +``` + +This command performs the following actions: + +1. Retrieves upgrade information directly from the blockchain about the next scheduled upgrade. +2. Downloads the new binary specified in the upgrade plan. +3. Verifies the binary's checksum (if required by configuration). +4. Places the new binary in the appropriate directory for Cosmovisor to use during the upgrade. + +The `prepare-upgrade` command provides detailed logging throughout the process, including: + +* The name and height of the upcoming upgrade +* The URL from which the new binary is being downloaded +* Confirmation of successful download and verification +* The path where the new binary has been placed + +Example output: + +```bash +INFO Preparing for upgrade name=v1.0.0 height=1000000 +INFO Downloading upgrade binary url=https://example.com/binary/v1.0.0?checksum=sha256:339911508de5e20b573ce902c500ee670589073485216bee8b045e853f24bce8 +INFO Upgrade preparation complete name=v1.0.0 height=1000000 +``` + +*Note: The current way of downloading manually and placing the binary at the right place would still work.* + ## Example: SimApp Upgrade The following instructions provide a demonstration of `cosmovisor` using the simulation application (`simapp`) shipped with the Cosmos SDK's source code. The following commands are to be run from within the `cosmos-sdk` repository. diff --git a/tools/cosmovisor/args.go b/tools/cosmovisor/args.go index be94fbadaf6c..6c6b5b7b0572 100644 --- a/tools/cosmovisor/args.go +++ b/tools/cosmovisor/args.go @@ -33,6 +33,7 @@ const ( EnvDataBackupPath = "DAEMON_DATA_BACKUP_DIR" EnvInterval = "DAEMON_POLL_INTERVAL" EnvPreupgradeMaxRetries = "DAEMON_PREUPGRADE_MAX_RETRIES" + EnvGRPCAddress = "DAEMON_GRPC_ADDRESS" EnvDisableLogs = "COSMOVISOR_DISABLE_LOGS" EnvColorLogs = "COSMOVISOR_COLOR_LOGS" EnvTimeFormatLogs = "COSMOVISOR_TIMEFORMAT_LOGS" @@ -63,6 +64,7 @@ type Config struct { UnsafeSkipBackup bool `toml:"unsafe_skip_backup" mapstructure:"unsafe_skip_backup" default:"false"` DataBackupPath string `toml:"daemon_data_backup_dir" mapstructure:"daemon_data_backup_dir"` PreUpgradeMaxRetries int `toml:"daemon_preupgrade_max_retries" mapstructure:"daemon_preupgrade_max_retries" default:"0"` + GRPCAddress string `toml:"daemon_grpc_address" mapstructure:"daemon_grpc_address"` DisableLogs bool `toml:"cosmovisor_disable_logs" mapstructure:"cosmovisor_disable_logs" default:"false"` ColorLogs bool `toml:"cosmovisor_color_logs" mapstructure:"cosmovisor_color_logs" default:"true"` TimeFormatLogs string `toml:"cosmovisor_timeformat_logs" mapstructure:"cosmovisor_timeformat_logs" default:"kitchen"` @@ -282,6 +284,11 @@ func GetConfigFromEnv(skipValidate bool) (*Config, error) { errs = append(errs, fmt.Errorf("%s could not be parsed to int: %w", EnvPreupgradeMaxRetries, err)) } + cfg.GRPCAddress = os.Getenv(EnvGRPCAddress) + if cfg.GRPCAddress == "" { + cfg.GRPCAddress = "localhost:9090" + } + if !skipValidate { errs = append(errs, cfg.validate()...) if len(errs) > 0 { diff --git a/tools/cosmovisor/args_test.go b/tools/cosmovisor/args_test.go index 74b75841ec5d..f121a3989d9f 100644 --- a/tools/cosmovisor/args_test.go +++ b/tools/cosmovisor/args_test.go @@ -765,8 +765,6 @@ func (s *argsTestSuite) TestGetConfigFromEnv() { } for _, tc := range tests { - tc := tc - s.T().Run(tc.name, func(t *testing.T) { s.setEnv(t, &tc.envVals) cfg, err := GetConfigFromEnv(false) diff --git a/tools/cosmovisor/cmd/cosmovisor/help.go b/tools/cosmovisor/cmd/cosmovisor/help.go index ba9c32afcbb5..6d6df59cef7b 100644 --- a/tools/cosmovisor/cmd/cosmovisor/help.go +++ b/tools/cosmovisor/cmd/cosmovisor/help.go @@ -18,7 +18,7 @@ the proposal. Cosmovisor interprets that data to perform an update: switch a cur and restart the App. Configuration of Cosmovisor is done through environment variables, which are -documented in: https://docs.cosmos.network/main/tooling/cosmovisor`, +documented in: https://docs.cosmos.network/main/build/tooling/cosmovisor`, cosmovisor.EnvName, cosmovisor.EnvHome, ) } diff --git a/tools/cosmovisor/cmd/cosmovisor/help_test.go b/tools/cosmovisor/cmd/cosmovisor/help_test.go index fe4e5d78c93b..48d7aa148436 100644 --- a/tools/cosmovisor/cmd/cosmovisor/help_test.go +++ b/tools/cosmovisor/cmd/cosmovisor/help_test.go @@ -12,7 +12,7 @@ func TestGetHelpText(t *testing.T) { expectedPieces := []string{ "Cosmovisor", cosmovisor.EnvName, cosmovisor.EnvHome, - "https://docs.cosmos.network/main/tooling/cosmovisor", + "https://docs.cosmos.network/main/build/tooling/cosmovisor", } actual := GetHelpText() diff --git a/tools/cosmovisor/cmd/cosmovisor/init_test.go b/tools/cosmovisor/cmd/cosmovisor/init_test.go index cea1349e3b39..97a082db729b 100644 --- a/tools/cosmovisor/cmd/cosmovisor/init_test.go +++ b/tools/cosmovisor/cmd/cosmovisor/init_test.go @@ -355,8 +355,6 @@ func (s *InitTestSuite) TestInitializeCosmovisorNegativeValidation() { } for _, tc := range tests { - tc := tc - s.T().Run(tc.name, func(t *testing.T) { s.setEnv(t, &tc.env) buffer, logger := s.NewCapturingLogger() diff --git a/tools/cosmovisor/cmd/cosmovisor/prepare_upgrade.go b/tools/cosmovisor/cmd/cosmovisor/prepare_upgrade.go new file mode 100644 index 000000000000..f15e88803a67 --- /dev/null +++ b/tools/cosmovisor/cmd/cosmovisor/prepare_upgrade.go @@ -0,0 +1,126 @@ +package main + +import ( + "context" + "crypto/tls" + "fmt" + "path/filepath" + "strings" + "time" + + "github.com/spf13/cobra" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials" + "google.golang.org/grpc/credentials/insecure" + + "cosmossdk.io/tools/cosmovisor" + "cosmossdk.io/x/upgrade/plan" + upgradetypes "cosmossdk.io/x/upgrade/types" +) + +func NewPrepareUpgradeCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "prepare-upgrade", + Short: "Prepare for the next upgrade", + Long: `Prepare for the next upgrade by downloading and verifying the upgrade binary. +This command will query the chain for the current upgrade plan and download the specified binary. +gRPC must be enabled on the node for this command to work.`, + RunE: prepareUpgradeHandler, + SilenceUsage: false, + Args: cobra.NoArgs, + } + + return cmd +} + +func prepareUpgradeHandler(cmd *cobra.Command, _ []string) error { + configPath, err := cmd.Flags().GetString(cosmovisor.FlagCosmovisorConfig) + if err != nil { + return fmt.Errorf("failed to get config flag: %w", err) + } + + cfg, err := cosmovisor.GetConfigFromFile(configPath) + if err != nil { + return fmt.Errorf("failed to get config: %w", err) + } + + logger := cfg.Logger(cmd.OutOrStdout()) + + grpcAddress := cfg.GRPCAddress + logger.Info("Using gRPC address", "address", grpcAddress) + + upgradeInfo, err := queryUpgradeInfoFromChain(grpcAddress) + if err != nil { + return fmt.Errorf("failed to query upgrade info: %w", err) + } + + if upgradeInfo == nil { + logger.Info("No active upgrade plan found") + return nil + } + + logger.Info("Preparing for upgrade", "name", upgradeInfo.Name, "height", upgradeInfo.Height) + + upgradeInfoParsed, err := plan.ParseInfo(upgradeInfo.Info, plan.ParseOptionEnforceChecksum(cfg.DownloadMustHaveChecksum)) + if err != nil { + return fmt.Errorf("failed to parse upgrade info: %w", err) + } + + binaryURL, err := cosmovisor.GetBinaryURL(upgradeInfoParsed.Binaries) + if err != nil { + return fmt.Errorf("binary URL not found in upgrade plan. Cannot prepare for upgrade: %w", err) + } + + logger.Info("Downloading upgrade binary", "url", binaryURL) + + upgradeBin := filepath.Join(cfg.UpgradeBin(upgradeInfo.Name), cfg.Name) + if err := plan.DownloadUpgrade(filepath.Dir(upgradeBin), binaryURL, cfg.Name); err != nil { + return fmt.Errorf("failed to download and verify binary: %w", err) + } + + logger.Info("Upgrade preparation complete", "name", upgradeInfo.Name, "height", upgradeInfo.Height) + + return nil +} + +func queryUpgradeInfoFromChain(grpcAddress string) (*upgradetypes.Plan, error) { + if grpcAddress == "" { + return nil, fmt.Errorf("gRPC address is empty") + } + + grpcConn, err := getClient(grpcAddress) + if err != nil { + return nil, fmt.Errorf("failed to open gRPC client: %w", err) + } + defer grpcConn.Close() + + queryClient := upgradetypes.NewQueryClient(grpcConn) + + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + defer cancel() + + res, err := queryClient.CurrentPlan(ctx, &upgradetypes.QueryCurrentPlanRequest{}) + if err != nil { + return nil, fmt.Errorf("failed to query current upgrade plan: %w", err) + } + + return res.Plan, nil +} + +func getClient(endpoint string) (*grpc.ClientConn, error) { + var creds credentials.TransportCredentials + if strings.HasPrefix(endpoint, "https://") { + tlsConfig := &tls.Config{ + MinVersion: tls.VersionTLS12, + } + creds = credentials.NewTLS(tlsConfig) + } else { + creds = insecure.NewCredentials() + } + + opts := []grpc.DialOption{ + grpc.WithTransportCredentials(creds), + } + + return grpc.NewClient(endpoint, opts...) +} diff --git a/tools/cosmovisor/cmd/cosmovisor/root.go b/tools/cosmovisor/cmd/cosmovisor/root.go index d9f6094d593c..5cd31f8aea5b 100644 --- a/tools/cosmovisor/cmd/cosmovisor/root.go +++ b/tools/cosmovisor/cmd/cosmovisor/root.go @@ -19,6 +19,8 @@ func NewRootCmd() *cobra.Command { configCmd, NewVersionCmd(), NewAddUpgradeCmd(), + NewShowUpgradeInfoCmd(), + NewPrepareUpgradeCmd(), ) rootCmd.PersistentFlags().StringP(cosmovisor.FlagCosmovisorConfig, "c", "", "path to cosmovisor config file") diff --git a/tools/cosmovisor/cmd/cosmovisor/show_upgrade.go b/tools/cosmovisor/cmd/cosmovisor/show_upgrade.go new file mode 100644 index 000000000000..aa37fa36d4e7 --- /dev/null +++ b/tools/cosmovisor/cmd/cosmovisor/show_upgrade.go @@ -0,0 +1,42 @@ +package main + +import ( + "fmt" + "os" + + "github.com/spf13/cobra" + + "cosmossdk.io/tools/cosmovisor" +) + +func NewShowUpgradeInfoCmd() *cobra.Command { + return &cobra.Command{ + Use: "show-upgrade-info", + Short: "Display current upgrade-info.json from data directory", + SilenceUsage: false, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + configPath, err := cmd.Flags().GetString(cosmovisor.FlagCosmovisorConfig) + if err != nil { + return fmt.Errorf("failed to get config flag: %w", err) + } + + cfg, err := cosmovisor.GetConfigFromFile(configPath) + if err != nil { + return err + } + + data, err := os.ReadFile(cfg.UpgradeInfoFilePath()) + if err != nil { + if os.IsNotExist(err) { + cmd.Printf("No upgrade info found at %s\n", cfg.UpgradeInfoFilePath()) + return nil + } + return fmt.Errorf("failed to read upgrade-info.json: %w", err) + } + + cmd.Println(string(data)) + return nil + }, + } +} diff --git a/tools/cosmovisor/go.mod b/tools/cosmovisor/go.mod index 008d8f1eae5a..d4b7d5328069 100644 --- a/tools/cosmovisor/go.mod +++ b/tools/cosmovisor/go.mod @@ -10,6 +10,7 @@ require ( github.com/spf13/cobra v1.8.1 github.com/spf13/viper v1.19.0 github.com/stretchr/testify v1.9.0 + google.golang.org/grpc v1.67.1 ) require ( @@ -19,7 +20,7 @@ require ( cloud.google.com/go/compute/metadata v0.5.0 // indirect cloud.google.com/go/iam v1.1.13 // indirect cloud.google.com/go/storage v1.43.0 // indirect - cosmossdk.io/api v0.7.5 // indirect + cosmossdk.io/api v0.7.6 // indirect cosmossdk.io/collections v0.4.0 // indirect cosmossdk.io/core v0.11.0 // indirect cosmossdk.io/depinject v1.0.0 // indirect @@ -78,7 +79,7 @@ require ( github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect github.com/gogo/googleapis v1.4.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang/glog v1.2.1 // indirect + github.com/golang/glog v1.2.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.4 // indirect github.com/golang/snappy v0.0.4 // indirect @@ -107,7 +108,7 @@ require ( github.com/hashicorp/hcl v1.0.0 // indirect github.com/hashicorp/yamux v0.1.1 // indirect github.com/hdevalence/ed25519consensus v0.2.0 // indirect - github.com/huandu/skiplist v1.2.0 // indirect + github.com/huandu/skiplist v1.2.1 // indirect github.com/iancoleman/strcase v0.3.0 // indirect github.com/improbable-eng/grpc-web v0.15.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect @@ -132,9 +133,9 @@ require ( github.com/petermattis/goid v0.0.0-20240503122002-4b96552b8156 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/client_golang v1.20.3 // indirect + github.com/prometheus/client_golang v1.20.4 // indirect github.com/prometheus/client_model v0.6.1 // indirect - github.com/prometheus/common v0.59.1 // indirect + github.com/prometheus/common v0.60.0 // indirect github.com/prometheus/procfs v0.15.1 // indirect github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect github.com/rogpeppe/go-internal v1.12.0 // indirect @@ -165,7 +166,7 @@ require ( golang.org/x/crypto v0.27.0 // indirect golang.org/x/exp v0.0.0-20240604190554-fc45aab8b7f8 // indirect golang.org/x/net v0.29.0 // indirect - golang.org/x/oauth2 v0.22.0 // indirect + golang.org/x/oauth2 v0.23.0 // indirect golang.org/x/sync v0.8.0 // indirect golang.org/x/sys v0.25.0 // indirect golang.org/x/term v0.24.0 // indirect @@ -174,8 +175,7 @@ require ( google.golang.org/api v0.192.0 // indirect google.golang.org/genproto v0.0.0-20240814211410-ddb44dafa142 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect - google.golang.org/grpc v1.66.2 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f // indirect google.golang.org/protobuf v1.34.2 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/tools/cosmovisor/go.sum b/tools/cosmovisor/go.sum index bddec9c4144c..0fdc70f990e7 100644 --- a/tools/cosmovisor/go.sum +++ b/tools/cosmovisor/go.sum @@ -188,8 +188,8 @@ cloud.google.com/go/webrisk v1.4.0/go.mod h1:Hn8X6Zr+ziE2aNd8SliSDWpEnSS1u4R9+xX cloud.google.com/go/webrisk v1.5.0/go.mod h1:iPG6fr52Tv7sGk0H6qUFzmL3HHZev1htXuWDEEsqMTg= cloud.google.com/go/workflows v1.6.0/go.mod h1:6t9F5h/unJz41YqfBmqSASJSXccBLtD1Vwf+KmJENM0= cloud.google.com/go/workflows v1.7.0/go.mod h1:JhSrZuVZWuiDfKEFxU0/F1PQjmpnpcoISEXH2bcHC3M= -cosmossdk.io/api v0.7.5 h1:eMPTReoNmGUm8DeiQL9DyM8sYDjEhWzL1+nLbI9DqtQ= -cosmossdk.io/api v0.7.5/go.mod h1:IcxpYS5fMemZGqyYtErK7OqvdM0C8kdW3dq8Q/XIG38= +cosmossdk.io/api v0.7.6 h1:PC20PcXy1xYKH2KU4RMurVoFjjKkCgYRbVAD4PdqUuY= +cosmossdk.io/api v0.7.6/go.mod h1:IcxpYS5fMemZGqyYtErK7OqvdM0C8kdW3dq8Q/XIG38= cosmossdk.io/collections v0.4.0 h1:PFmwj2W8szgpD5nOd8GWH6AbYNi1f2J6akWXJ7P5t9s= cosmossdk.io/collections v0.4.0/go.mod h1:oa5lUING2dP+gdDquow+QjlF45eL1t4TJDypgGd+tv0= cosmossdk.io/core v0.11.0 h1:vtIafqUi+1ZNAE/oxLOQQ7Oek2n4S48SWLG8h/+wdbo= @@ -457,8 +457,8 @@ github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXP github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/glog v1.2.1 h1:OptwRhECazUx5ix5TTWC3EZhsZEHWcYWY4FQHTIubm4= -github.com/golang/glog v1.2.1/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= +github.com/golang/glog v1.2.2 h1:1+mZ9upx1Dh6FmUTFR1naJ77miKiXgALjWOZ3NVFPmY= +github.com/golang/glog v1.2.2/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -650,8 +650,8 @@ github.com/hdevalence/ed25519consensus v0.2.0/go.mod h1:w3BHWjwJbFU29IRHL1Iqkw3s github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/huandu/go-assert v1.1.5 h1:fjemmA7sSfYHJD7CUqs9qTwwfdNAx7/j2/ZlHXzNB3c= github.com/huandu/go-assert v1.1.5/go.mod h1:yOLvuqZwmcHIC5rIzrBhT7D3Q9c3GFnd0JrPVhn/06U= -github.com/huandu/skiplist v1.2.0 h1:gox56QD77HzSC0w+Ws3MH3iie755GBJU1OER3h5VsYw= -github.com/huandu/skiplist v1.2.0/go.mod h1:7v3iFjLcSAzO4fN5B8dvebvo/qsfumiLiDXMrPiHF9w= +github.com/huandu/skiplist v1.2.1 h1:dTi93MgjwErA/8idWTzIw4Y1kZsMWx35fmI2c8Rij7w= +github.com/huandu/skiplist v1.2.1/go.mod h1:7v3iFjLcSAzO4fN5B8dvebvo/qsfumiLiDXMrPiHF9w= github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI= github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= @@ -838,8 +838,8 @@ 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.20.3 h1:oPksm4K8B+Vt35tUhw6GbSNSgVlVSBH0qELP/7u83l4= -github.com/prometheus/client_golang v1.20.3/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_golang v1.20.4 h1:Tgh3Yr67PaOv/uTqloMsCEdeuFTatm5zIq5+qNN23vI= +github.com/prometheus/client_golang v1.20.4/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -854,8 +854,8 @@ 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.59.1 h1:LXb1quJHWm1P6wq/U824uxYi4Sg0oGvNeUm1z5dJoX0= -github.com/prometheus/common v0.59.1/go.mod h1:GpWM7dewqmVYcd7SmRaiWVe9SSqjf0UrwnYnpEZNuT0= +github.com/prometheus/common v0.60.0 h1:+V9PAREWNvJMAuJ1x1BaWl9dewMW4YrHZQbx0sJNllA= +github.com/prometheus/common v0.60.0/go.mod h1:h0LYf1R1deLSKtD4Vdg8gy4RuOvENW2J/h19V5NADQw= 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= @@ -1142,8 +1142,8 @@ golang.org/x/oauth2 v0.0.0-20220822191816-0ebed06d0094/go.mod h1:h4gKUeWbJ4rQPri golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= golang.org/x/oauth2 v0.1.0/go.mod h1:G9FE4dLTsbXUu90h/Pf85g4w1D+SSAgR+q46nJZ8M4A= -golang.org/x/oauth2 v0.22.0 h1:BzDx2FehcG7jJwgWLELCdmLuxk2i+x9UDpSiss2u0ZA= -golang.org/x/oauth2 v0.22.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/oauth2 v0.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs= +golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= 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= @@ -1516,8 +1516,8 @@ google.golang.org/genproto v0.0.0-20240814211410-ddb44dafa142 h1:oLiyxGgE+rt22du google.golang.org/genproto v0.0.0-20240814211410-ddb44dafa142/go.mod h1:G11eXq53iI5Q+kyNOmCvnzBaxEA2Q/Ik5Tj7nqBE8j4= google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 h1:wKguEg1hsxI2/L3hUYrpo1RVi48K+uTyzKqprwLXsb8= google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142/go.mod h1:d6be+8HhtEtucleCbxpPW9PA9XwISACu8nvpPqF0BVo= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:pPJltXNxVzT4pK9yD8vR9X75DaWYYmLGMsEvBfFQZzQ= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f h1:cUMEy+8oS78BWIH9OWazBkzbr090Od9tWBNtZHkOhf0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= 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.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= @@ -1559,8 +1559,8 @@ google.golang.org/grpc v1.48.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACu google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= google.golang.org/grpc v1.50.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= -google.golang.org/grpc v1.66.2 h1:3QdXkuq3Bkh7w+ywLdLvM56cmGvQHUMZpiCzt6Rqaoo= -google.golang.org/grpc v1.66.2/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y= +google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E= +google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= 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= diff --git a/tools/cosmovisor/testdata/download/cosmovisor/genesis/bin/autod b/tools/cosmovisor/testdata/download/cosmovisor/genesis/bin/autod index f2573651ad3f..c8d7e1e30fa7 100755 --- a/tools/cosmovisor/testdata/download/cosmovisor/genesis/bin/autod +++ b/tools/cosmovisor/testdata/download/cosmovisor/genesis/bin/autod @@ -6,7 +6,13 @@ echo 'ERROR: UPGRADE "chain2" NEEDED at height: 49: zip_binary' # create upgrade info # this info contains directly information about binaries (in chain2->chain3 update we test with info containing a link to the file with an address for the new chain binary) -echo '{"name":"chain2","height":49,"info":"{\"binaries\":{\"linux/amd64\":\"https://github.com/cosmos/cosmos-sdk/raw/main/tools/cosmovisor/testdata/repo/chain2-zip_bin/autod.zip?checksum=sha256:13767eb0b57bf51a0f43d49f6277d5df97d4dec672dc39822d23a82fb8e70a7b\"}}"}' >$3 +cat > "$3" < $3 -echo '{"name":"chain3","height":936,"info":"https://github.com/cosmos/cosmos-sdk/raw/main/tools/cosmovisor/testdata/repo/ref_to_chain3-zip_dir.json?checksum=sha256:a95075f4dd83bc9f0f556ef73e64ce000f9bf3a6beeb9d4ae32f594b1417ef7a"}' >$3 +cat > "$3" < B[Execute Signature Verification Ante Handler] + B --> D{Is signer an x/accounts account?} + D -->|No| E[Continue with signature verification ante handler] + D -->|Yes| F{Does account handle MsgAuthenticate?} + F -->|No| G[Fail TX: Non-externally owned account] + F -->|Yes| H[Invoke signer account MsgAuthenticate] + E --> I[End] + G --> I + H --> I +``` + + +## Implementing the Authentication Interface + +To implement the Authentication interface, an account must handle the execution of `MsgAuthenticate`. Here's an example of how to do this: + +```go +package base + +import ( + "context" + "errors" + aa_interface_v1 "github.com/cosmos/cosmos-sdk/x/accounts/interfaces/account_abstraction/v1" + "github.com/cosmos/cosmos-sdk/x/accounts/std" +) + +// Account represents a base account structure +type Account struct { + // Account fields... +} + +// Authenticate implements the authentication flow for an abstracted base account. +func (a Account) Authenticate(ctx context.Context, msg *aa_interface_v1.MsgAuthenticate) (*aa_interface_v1.MsgAuthenticateResponse, error) { + if !accountstd.SenderIsAccountsModule(ctx) { + return nil, errors.New("unauthorized: only accounts module is allowed to call this") + } + // Implement your authentication logic here + // ... + return &aa_interface_v1.MsgAuthenticateResponse{}, nil +} + +// RegisterExecuteHandlers registers the execution handlers for the account. +func (a Account) RegisterExecuteHandlers(builder *accountstd.ExecuteBuilder) { + accountstd.RegisterExecuteHandler(builder, a.SwapPubKey) // Other handlers + accountstd.RegisterExecuteHandler(builder, a.Authenticate) // Implements the Authentication interface +} +``` + +### Key Implementation Points + +1. **Sender Verification**: Always verify that the sender is the x/accounts module. This prevents unauthorized accounts from triggering authentication. +2. **Authentication Safety**: Ensure your authentication mechanism is secure: + - Prevent replay attacks by making it impossible to reuse the same action with the same signature. + + +#### Implementation example + +Please find an example [here](./defaults/base/account.go). + +# Supporting Custom Accounts in the x/auth gRPC Server + +## Overview + +The x/auth module provides a mechanism for custom account types to be exposed via its `Account` and `AccountInfo` gRPC +queries. This feature is particularly useful for ensuring compatibility with existing wallets that have not yet integrated +with x/accounts but still need to parse account information post-migration. + +## Implementation + +To support this feature, your custom account type needs to implement the `auth.QueryLegacyAccount` handler. Here are some important points to consider: + +1. **Selective Implementation**: This implementation is not required for every account type. It's only necessary for accounts you want to expose through the x/auth gRPC `Account` and `AccountInfo` methods. +2. **Flexible Response**: The `info` field in the `QueryLegacyAccountResponse` is optional. If your custom account cannot be represented as a `BaseAccount`, you can leave this field empty. + +## Example Implementation + +A concrete example of implementation can be found in `defaults/base/account.go`. Here's a simplified version: + +```go +func (a Account) AuthRetroCompatibility(ctx context.Context, _ *authtypes.QueryLegacyAccount) (*authtypes.QueryLegacyAccountResponse, error) { + seq := a.GetSequence() + num := a.GetNumber() + address := a.GetAddress() + pubKey := a.GetPubKey() + + baseAccount := &authtypes.BaseAccount{ + AccountNumber: num, + Sequence: seq, + Address: address, + } + + // Convert pubKey to Any type + pubKeyAny, err := gogotypes.NewAnyWithValue(pubKey) + if err != nil { + return nil, err + } + baseAccount.PubKey = pubKeyAny + + // Convert the entire baseAccount to Any type + accountAny, err := gogotypes.NewAnyWithValue(baseAccount) + if err != nil { + return nil, err + } + + return &authtypes.QueryLegacyAccountResponse{ + Account: accountAny, + Info: baseAccount, + }, nil +} +``` + +## Usage Notes + +* Implement this handler only for account types you want to expose via x/auth gRPC methods. +* The `info` field in the response can be nil if your account doesn't fit the `BaseAccount` structure. # Genesis @@ -45,4 +191,4 @@ For example, given the following `genesis.json` file: } ``` -The accounts module will run the lockup account initialization message. \ No newline at end of file +The accounts module will run the lockup account initialization message. diff --git a/x/accounts/accountstd/exports.go b/x/accounts/accountstd/exports.go index 24ffc17c1e98..2ebe1acb82fb 100644 --- a/x/accounts/accountstd/exports.go +++ b/x/accounts/accountstd/exports.go @@ -4,6 +4,7 @@ package accountstd import ( "bytes" "context" + "errors" "fmt" "cosmossdk.io/core/transaction" @@ -13,7 +14,10 @@ import ( "github.com/cosmos/cosmos-sdk/types/address" ) -var accountsModuleAddress = address.Module("accounts") +var ( + accountsModuleAddress = address.Module("accounts") + ErrInvalidType = errors.New("invalid type") +) // Interface is the exported interface of an Account. type Interface = implementation.Account @@ -30,6 +34,16 @@ type InitBuilder = implementation.InitBuilder // AccountCreatorFunc is the exported type of AccountCreatorFunc. type AccountCreatorFunc = implementation.AccountCreatorFunc +func DIAccount[A Interface](name string, constructor func(deps Dependencies) (A, error)) DepinjectAccount { + return DepinjectAccount{MakeAccount: AddAccount(name, constructor)} +} + +type DepinjectAccount struct { + MakeAccount AccountCreatorFunc +} + +func (DepinjectAccount) IsManyPerContainerType() {} + // Dependencies is the exported type of Dependencies. type Dependencies = implementation.Dependencies @@ -91,13 +105,21 @@ func SenderIsAccountsModule(ctx context.Context) bool { // returns nil. func Funds(ctx context.Context) sdk.Coins { return implementation.Funds(ctx) } -func ExecModule(ctx context.Context, msg transaction.Msg) (transaction.Msg, error) { - return implementation.ExecModule(ctx, msg) +func ExecModule[MsgResp, Msg transaction.Msg](ctx context.Context, msg Msg) (resp MsgResp, err error) { + untyped, err := implementation.ExecModule(ctx, msg) + if err != nil { + return resp, err + } + return assertOrErr[MsgResp](untyped) } // QueryModule can be used by an account to execute a module query. -func QueryModule(ctx context.Context, req transaction.Msg) (transaction.Msg, error) { - return implementation.QueryModule(ctx, req) +func QueryModule[Resp, Req transaction.Msg](ctx context.Context, req Req) (resp Resp, err error) { + untyped, err := implementation.QueryModule(ctx, req) + if err != nil { + return resp, err + } + return assertOrErr[Resp](untyped) } // UnpackAny unpacks a protobuf Any message generically. @@ -120,7 +142,7 @@ func ExecModuleAnys(ctx context.Context, msgs []*implementation.Any) ([]*impleme if err != nil { return nil, fmt.Errorf("error unpacking message %d: %w", i, err) } - resp, err := ExecModule(ctx, concreteMessage) + resp, err := implementation.ExecModule(ctx, concreteMessage) if err != nil { return nil, fmt.Errorf("error executing message %d: %w", i, err) } @@ -133,3 +155,12 @@ func ExecModuleAnys(ctx context.Context, msgs []*implementation.Any) ([]*impleme } return responses, nil } + +// asserts the given any to the provided generic, returns ErrInvalidType if it can't. +func assertOrErr[T any](r any) (concrete T, err error) { + concrete, ok := r.(T) + if !ok { + return concrete, ErrInvalidType + } + return concrete, nil +} diff --git a/x/accounts/cli/cli_test.go b/x/accounts/cli/cli_test.go index aa5c2521852d..5e9c188d1d68 100644 --- a/x/accounts/cli/cli_test.go +++ b/x/accounts/cli/cli_test.go @@ -119,7 +119,6 @@ func (s *CLITestSuite) TestTxInitCmd() { } for _, tc := range testCases { - tc := tc s.Run(tc.name, func() { ctx := svrcmd.CreateExecuteContext(context.Background()) diff --git a/x/accounts/defaults/base/CHANGELOG.md b/x/accounts/defaults/base/CHANGELOG.md new file mode 100644 index 000000000000..7ce64dffb257 --- /dev/null +++ b/x/accounts/defaults/base/CHANGELOG.md @@ -0,0 +1,26 @@ + + +# Changelog + +## [Unreleased] \ No newline at end of file diff --git a/x/accounts/defaults/base/account.go b/x/accounts/defaults/base/account.go index eef6e6c2153e..b227899aec75 100644 --- a/x/accounts/defaults/base/account.go +++ b/x/accounts/defaults/base/account.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" + gogotypes "github.com/cosmos/gogoproto/types/any" "google.golang.org/protobuf/proto" "google.golang.org/protobuf/types/known/anypb" @@ -21,6 +22,7 @@ import ( codectypes "github.com/cosmos/cosmos-sdk/codec/types" "github.com/cosmos/cosmos-sdk/types/tx" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" ) var ( @@ -31,6 +33,8 @@ var ( type Option func(a *Account) +func (Option) IsManyPerContainerType() {} + func NewAccount(name string, handlerMap *signing.HandlerMap, options ...Option) accountstd.AccountCreatorFunc { return func(deps accountstd.Dependencies) (string, accountstd.Interface, error) { acc := Account{ @@ -68,6 +72,12 @@ type Account struct { } func (a Account) Init(ctx context.Context, msg *v1.MsgInit) (*v1.MsgInitResponse, error) { + if msg.InitSequence != 0 { + err := a.Sequence.Set(ctx, msg.InitSequence) + if err != nil { + return nil, err + } + } return &v1.MsgInitResponse{}, a.savePubKey(ctx, msg.PubKey) } @@ -168,17 +178,12 @@ func (a Account) computeSignerData(ctx context.Context) (PubKey, signing.SignerD } func (a Account) getNumber(ctx context.Context, addrStr string) (uint64, error) { - accNum, err := accountstd.QueryModule(ctx, &accountsv1.AccountNumberRequest{Address: addrStr}) + accNum, err := accountstd.QueryModule[*accountsv1.AccountNumberResponse](ctx, &accountsv1.AccountNumberRequest{Address: addrStr}) if err != nil { return 0, err } - resp, ok := accNum.(*accountsv1.AccountNumberResponse) - if !ok { - return 0, fmt.Errorf("unexpected response type: %T", accNum) - } - - return resp.Number, nil + return accNum.Number, nil } func (a Account) getTxData(msg *aa_interface_v1.MsgAuthenticate) (signing.TxData, error) { @@ -261,6 +266,60 @@ func (a Account) QuerySequence(ctx context.Context, _ *v1.QuerySequence) (*v1.Qu return &v1.QuerySequenceResponse{Sequence: seq}, nil } +func (a Account) QueryPubKey(ctx context.Context, _ *v1.QueryPubKey) (*v1.QueryPubKeyResponse, error) { + pubKey, err := a.loadPubKey(ctx) + if err != nil { + return nil, err + } + anyPubKey, err := codectypes.NewAnyWithValue(pubKey) + if err != nil { + return nil, err + } + return &v1.QueryPubKeyResponse{PubKey: anyPubKey}, nil +} + +func (a Account) AuthRetroCompatibility(ctx context.Context, _ *authtypes.QueryLegacyAccount) (*authtypes.QueryLegacyAccountResponse, error) { + addr, err := a.addrCodec.BytesToString(accountstd.Whoami(ctx)) + if err != nil { + return nil, err + } + + accNumber, err := accountstd.QueryModule[*accountsv1.AccountNumberResponse](ctx, &accountsv1.AccountNumberRequest{Address: addr}) + if err != nil { + return nil, err + } + pk, err := a.loadPubKey(ctx) + if err != nil { + return nil, err + } + anyPk, err := gogotypes.NewAnyWithCacheWithValue(pk) + if err != nil { + return nil, err + } + + seq, err := a.Sequence.Peek(ctx) + if err != nil { + return nil, err + } + + baseAccount := &authtypes.BaseAccount{ + Address: addr, + PubKey: anyPk, + AccountNumber: accNumber.Number, + Sequence: seq, + } + + baseAccountAny, err := gogotypes.NewAnyWithCacheWithValue(baseAccount) + if err != nil { + return nil, err + } + + return &authtypes.QueryLegacyAccountResponse{ + Account: baseAccountAny, + Base: baseAccount, + }, nil +} + func (a Account) RegisterInitHandler(builder *accountstd.InitBuilder) { accountstd.RegisterInitHandler(builder, a.Init) } @@ -272,4 +331,6 @@ func (a Account) RegisterExecuteHandlers(builder *accountstd.ExecuteBuilder) { func (a Account) RegisterQueryHandlers(builder *accountstd.QueryBuilder) { accountstd.RegisterQueryHandler(builder, a.QuerySequence) + accountstd.RegisterQueryHandler(builder, a.QueryPubKey) + accountstd.RegisterQueryHandler(builder, a.AuthRetroCompatibility) } diff --git a/x/accounts/defaults/base/depinject/depinject.go b/x/accounts/defaults/base/depinject/depinject.go new file mode 100644 index 000000000000..6943b5dcaafd --- /dev/null +++ b/x/accounts/defaults/base/depinject/depinject.go @@ -0,0 +1,31 @@ +package basedepinject + +import ( + "cosmossdk.io/depinject" + "cosmossdk.io/x/accounts/accountstd" + "cosmossdk.io/x/accounts/defaults/base" + "cosmossdk.io/x/tx/signing" +) + +type Inputs struct { + depinject.In + + SignHandlersMap *signing.HandlerMap + Options []base.Option +} + +func ProvideAccount(in Inputs) accountstd.DepinjectAccount { + return accountstd.DepinjectAccount{MakeAccount: base.NewAccount("base", in.SignHandlersMap, in.Options...)} +} + +func ProvideSecp256K1PubKey() base.Option { + return base.WithSecp256K1PubKey() +} + +func ProvideCustomPubkey[T any, PT base.PubKeyG[T]]() base.Option { + return base.WithPubKey[T, PT]() +} + +func ProvideCustomPubKeyAndValidationFunc[T any, PT base.PubKeyG[T]](validateFn func(PT) error) base.Option { + return base.WithPubKeyWithValidationFunc(validateFn) +} diff --git a/x/accounts/defaults/base/go.mod b/x/accounts/defaults/base/go.mod new file mode 100644 index 000000000000..ea0ef43187dc --- /dev/null +++ b/x/accounts/defaults/base/go.mod @@ -0,0 +1,180 @@ +module cosmossdk.io/x/accounts/defaults/base + +go 1.23.1 + +require ( + cosmossdk.io/api v0.7.6 + cosmossdk.io/collections v0.4.0 + cosmossdk.io/core v1.0.0-alpha.4 + cosmossdk.io/depinject v1.0.0 + cosmossdk.io/x/accounts v0.0.0-20240913065641-0064ccbce64e + cosmossdk.io/x/tx v0.13.3 + github.com/cosmos/cosmos-sdk v0.53.0 + github.com/cosmos/gogoproto v1.7.0 + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 + github.com/stretchr/testify v1.9.0 + google.golang.org/protobuf v1.34.2 +) + +require ( + buf.build/gen/go/cometbft/cometbft/protocolbuffers/go v1.34.2-20240701160653-fedbb9acfd2f.2 // indirect + buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.34.2-20240130113600-88ef6483f90f.2 // indirect + cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29 // indirect + cosmossdk.io/errors v1.0.1 // indirect + cosmossdk.io/log v1.4.1 // indirect + cosmossdk.io/math v1.3.0 // indirect + cosmossdk.io/schema v0.3.1-0.20240930054013-7c6e0388a3f9 // indirect + cosmossdk.io/store v1.1.1-0.20240418092142-896cdf1971bc // indirect + cosmossdk.io/x/bank v0.0.0-20240226161501-23359a0b6d91 // indirect + cosmossdk.io/x/staking v0.0.0-00010101000000-000000000000 // indirect + filippo.io/edwards25519 v1.1.0 // indirect + github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect + github.com/99designs/keyring v1.2.2 // indirect + github.com/DataDog/datadog-go v4.8.3+incompatible // indirect + github.com/DataDog/zstd v1.5.5 // indirect + github.com/Microsoft/go-winio v0.6.1 // indirect + github.com/beorn7/perks v1.0.1 // indirect + github.com/bgentry/speakeasy v0.2.0 // indirect + github.com/btcsuite/btcd/btcec/v2 v2.3.4 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect + github.com/cockroachdb/errors v1.11.3 // indirect + github.com/cockroachdb/fifo v0.0.0-20240606204812-0bbfbd93a7ce // indirect + github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect + github.com/cockroachdb/pebble v1.1.2 // indirect + github.com/cockroachdb/redact v1.1.5 // indirect + github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect + github.com/cometbft/cometbft v1.0.0-rc1.0.20240908111210-ab0be101882f // indirect + github.com/cometbft/cometbft-db v0.15.0 // indirect + github.com/cometbft/cometbft/api v1.0.0-rc.1 // indirect + github.com/cosmos/btcutil v1.0.5 // indirect + github.com/cosmos/cosmos-db v1.0.3-0.20240911104526-ddc3f09bfc22 // indirect + github.com/cosmos/cosmos-proto v1.0.0-beta.5 // indirect + github.com/cosmos/crypto v0.1.2 // indirect + github.com/cosmos/go-bip39 v1.0.0 // indirect + github.com/cosmos/gogogateway v1.2.0 // indirect + github.com/cosmos/iavl v1.3.0 // indirect + github.com/cosmos/ics23/go v0.11.0 // indirect + github.com/cosmos/ledger-cosmos-go v0.13.3 // indirect + github.com/danieljoos/wincred v1.2.1 // indirect + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/dgraph-io/badger/v4 v4.3.0 // indirect + github.com/dgraph-io/ristretto v0.1.2-0.20240116140435-c67e07994f91 // indirect + github.com/dustin/go-humanize v1.0.1 // indirect + github.com/dvsekhvalnov/jose2go v1.6.0 // indirect + github.com/emicklei/dot v1.6.2 // indirect + github.com/fatih/color v1.17.0 // indirect + github.com/felixge/httpsnoop v1.0.4 // indirect + github.com/fsnotify/fsnotify v1.7.0 // indirect + github.com/getsentry/sentry-go v0.27.0 // indirect + github.com/go-kit/kit v0.13.0 // indirect + github.com/go-kit/log v0.2.1 // indirect + github.com/go-logfmt/logfmt v0.6.0 // indirect + github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect + github.com/gogo/googleapis v1.4.1 // indirect + github.com/gogo/protobuf v1.3.2 // indirect + github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect + github.com/golang/protobuf v1.5.4 // indirect + github.com/golang/snappy v0.0.4 // indirect + github.com/google/btree v1.1.3 // indirect + github.com/google/flatbuffers v2.0.8+incompatible // indirect + github.com/google/go-cmp v0.6.0 // indirect + github.com/google/orderedcode v0.0.1 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/gorilla/handlers v1.5.2 // indirect + github.com/gorilla/mux v1.8.1 // indirect + github.com/gorilla/websocket v1.5.3 // indirect + github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 // indirect + github.com/grpc-ecosystem/grpc-gateway v1.16.0 // indirect + github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c // indirect + github.com/hashicorp/go-hclog v1.6.3 // indirect + github.com/hashicorp/go-immutable-radix v1.3.1 // indirect + github.com/hashicorp/go-metrics v0.5.3 // indirect + github.com/hashicorp/go-plugin v1.6.1 // indirect + github.com/hashicorp/golang-lru v1.0.2 // indirect + github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect + github.com/hashicorp/hcl v1.0.0 // indirect + github.com/hashicorp/yamux v0.1.1 // indirect + github.com/hdevalence/ed25519consensus v0.2.0 // indirect + github.com/huandu/skiplist v1.2.1 // indirect + github.com/iancoleman/strcase v0.3.0 // indirect + github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/jmhodges/levigo v1.0.0 // indirect + github.com/klauspost/compress v1.17.9 // indirect + github.com/kr/pretty v0.3.1 // indirect + github.com/kr/text v0.2.0 // indirect + github.com/lib/pq v1.10.9 // indirect + github.com/linxGnu/grocksdb v1.9.3 // indirect + github.com/magiconair/properties v1.8.7 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/minio/highwayhash v1.0.3 // 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/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect + github.com/oasisprotocol/curve25519-voi v0.0.0-20230904125328-1f23a7beb09a // indirect + github.com/oklog/run v1.1.0 // indirect + github.com/pelletier/go-toml/v2 v2.2.3 // indirect + github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect + github.com/prometheus/client_golang v1.20.4 // indirect + github.com/prometheus/client_model v0.6.1 // indirect + github.com/prometheus/common v0.60.0 // indirect + github.com/prometheus/procfs v0.15.1 // indirect + github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect + github.com/rogpeppe/go-internal v1.12.0 // indirect + github.com/rs/cors v1.11.0 // indirect + github.com/rs/zerolog v1.33.0 // indirect + github.com/sagikazarmark/locafero v0.4.0 // indirect + github.com/sagikazarmark/slog-shim v0.1.0 // indirect + github.com/sasha-s/go-deadlock v0.3.5 // indirect + github.com/sourcegraph/conc v0.3.0 // indirect + github.com/spf13/afero v1.11.0 // indirect + github.com/spf13/cast v1.7.0 // indirect + github.com/spf13/cobra v1.8.1 // indirect + github.com/spf13/pflag v1.0.5 // indirect + github.com/spf13/viper v1.19.0 // indirect + github.com/subosito/gotenv v1.6.0 // indirect + github.com/supranational/blst v0.3.13 // indirect + github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d // indirect + github.com/tendermint/go-amino v0.16.0 // indirect + github.com/tidwall/btree v1.7.0 // indirect + github.com/zondax/hid v0.9.2 // indirect + github.com/zondax/ledger-go v0.14.3 // indirect + gitlab.com/yawning/secp256k1-voi v0.0.0-20230925100816-f2616030848b // indirect + gitlab.com/yawning/tuplehash v0.0.0-20230713102510-df83abbf9a02 // indirect + go.etcd.io/bbolt v1.4.0-alpha.0.0.20240404170359-43604f3112c5 // indirect + go.opencensus.io v0.24.0 // indirect + go.uber.org/multierr v1.11.0 // indirect + golang.org/x/crypto v0.27.0 // indirect + golang.org/x/exp v0.0.0-20240531132922-fd00a4e0eefc // indirect + golang.org/x/mod v0.17.0 // indirect + golang.org/x/net v0.29.0 // indirect + golang.org/x/sync v0.8.0 // indirect + golang.org/x/sys v0.25.0 // indirect + golang.org/x/term v0.24.0 // indirect + golang.org/x/text v0.18.0 // indirect + golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect + google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f // indirect + google.golang.org/grpc v1.67.1 // indirect + gopkg.in/ini.v1 v1.67.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect + gotest.tools/v3 v3.5.1 // indirect + pgregory.net/rapid v1.1.0 // indirect + sigs.k8s.io/yaml v1.4.0 // indirect +) + +replace github.com/cosmos/cosmos-sdk => ../../../../. + +replace ( + cosmossdk.io/api => ../../../../api + cosmossdk.io/collections => ../../../../collections // TODO tag new collections ASAP + cosmossdk.io/store => ../../../../store + cosmossdk.io/x/accounts => ../../. + cosmossdk.io/x/bank => ../../../bank + cosmossdk.io/x/staking => ../../../staking + cosmossdk.io/x/tx => ../../../tx +) diff --git a/x/accounts/defaults/base/go.sum b/x/accounts/defaults/base/go.sum new file mode 100644 index 000000000000..25dd6bf3bb3f --- /dev/null +++ b/x/accounts/defaults/base/go.sum @@ -0,0 +1,697 @@ +buf.build/gen/go/cometbft/cometbft/protocolbuffers/go v1.34.2-20240701160653-fedbb9acfd2f.2 h1:90/4O5QkHb8EZdA2SAhueRzYw6u5ZHCPKtReFqshnTY= +buf.build/gen/go/cometbft/cometbft/protocolbuffers/go v1.34.2-20240701160653-fedbb9acfd2f.2/go.mod h1:1+3gJj2NvZ1mTLAtHu+lMhOjGgQPiCKCeo+9MBww0Eo= +buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.34.2-20240130113600-88ef6483f90f.2 h1:b7EEYTUHmWSBEyISHlHvXbJPqtKiHRuUignL1tsHnNQ= +buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.34.2-20240130113600-88ef6483f90f.2/go.mod h1:HqcXMSa5qnNuakaMUo+hWhF51mKbcrZxGl9Vp5EeJXc= +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cosmossdk.io/core v1.0.0-alpha.4 h1:9iuroT9ejDYETCsGkzkvs/wAY/5UFl7nCIINFRxyMJY= +cosmossdk.io/core v1.0.0-alpha.4/go.mod h1:3u9cWq1FAVtiiCrDPpo4LhR+9V6k/ycSG4/Y/tREWCY= +cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29 h1:NxxUo0GMJUbIuVg0R70e3cbn9eFTEuMr7ev1AFvypdY= +cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29/go.mod h1:8s2tPeJtSiQuoyPmr2Ag7meikonISO4Fv4MoO8+ORrs= +cosmossdk.io/depinject v1.0.0 h1:dQaTu6+O6askNXO06+jyeUAnF2/ssKwrrszP9t5q050= +cosmossdk.io/depinject v1.0.0/go.mod h1:zxK/h3HgHoA/eJVtiSsoaRaRA2D5U4cJ5thIG4ssbB8= +cosmossdk.io/errors v1.0.1 h1:bzu+Kcr0kS/1DuPBtUFdWjzLqyUuCiyHjyJB6srBV/0= +cosmossdk.io/errors v1.0.1/go.mod h1:MeelVSZThMi4bEakzhhhE/CKqVv3nOJDA25bIqRDu/U= +cosmossdk.io/log v1.4.1 h1:wKdjfDRbDyZRuWa8M+9nuvpVYxrEOwbD/CA8hvhU8QM= +cosmossdk.io/log v1.4.1/go.mod h1:k08v0Pyq+gCP6phvdI6RCGhLf/r425UT6Rk/m+o74rU= +cosmossdk.io/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE= +cosmossdk.io/math v1.3.0/go.mod h1:vnRTxewy+M7BtXBNFybkuhSH4WfedVAAnERHgVFhp3k= +cosmossdk.io/schema v0.3.1-0.20240930054013-7c6e0388a3f9 h1:DmOoS/1PeY6Ih0hAVlJ69kLMUrLV+TCbfICrZtB1vdU= +cosmossdk.io/schema v0.3.1-0.20240930054013-7c6e0388a3f9/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= +filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= +filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= +github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMbk2FiG/kXiLl8BRyzTWDw7gX/Hz7Dd5eDMs= +github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4/go.mod h1:hN7oaIRCjzsZ2dE+yG5k+rsdt3qcwykqK6HVGcKwsw4= +github.com/99designs/keyring v1.2.2 h1:pZd3neh/EmUzWONb35LxQfvuY7kiSXAq3HQd97+XBn0= +github.com/99designs/keyring v1.2.2/go.mod h1:wes/FrByc8j7lFOAGLGSNEg8f/PaI3cgTBqhFkHUrPk= +github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0= +github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= +github.com/DataDog/datadog-go v4.8.3+incompatible h1:fNGaYSuObuQb5nzeTQqowRAd9bpDIRRV4/gUtIBjh8Q= +github.com/DataDog/datadog-go v4.8.3+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= +github.com/DataDog/zstd v1.5.5 h1:oWf5W7GtOLgp6bciQYDmhHHjdhYkALu6S/5Ni9ZgSvQ= +github.com/DataDog/zstd v1.5.5/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= +github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= +github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= +github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw= +github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk= +github.com/VividCortex/gohistogram v1.0.0 h1:6+hBz+qvs0JOrrNhhmR7lFxo5sINxBCGXrdtl/UvroE= +github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= +github.com/adlio/schema v1.3.6 h1:k1/zc2jNfeiZBA5aFTRy37jlBIuCkXCm0XmvpzCKI9I= +github.com/adlio/schema v1.3.6/go.mod h1:qkxwLgPBd1FgLRHYVCmQT/rrBr3JH38J9LjmVzWNudg= +github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= +github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= +github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bgentry/speakeasy v0.2.0 h1:tgObeVOf8WAvtuAX6DhJ4xks4CFNwPDZiqzGqIHE51E= +github.com/bgentry/speakeasy v0.2.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= +github.com/btcsuite/btcd/btcec/v2 v2.3.4 h1:3EJjcN70HCu/mwqlUsGK8GcNVyLVxFDlWurTXGPFfiQ= +github.com/btcsuite/btcd/btcec/v2 v2.3.4/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= +github.com/btcsuite/btcd/btcutil v1.1.6 h1:zFL2+c3Lb9gEgqKNzowKUPQNb8jV7v5Oaodi/AYFd6c= +github.com/btcsuite/btcd/btcutil v1.1.6/go.mod h1:9dFymx8HpuLqBnsPELrImQeTQfKBQqzqGbbV3jK55aE= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= +github.com/bufbuild/protocompile v0.4.0 h1:LbFKd2XowZvQ/kajzguUp2DC9UEIQhIq77fZZlaQsNA= +github.com/bufbuild/protocompile v0.4.0/go.mod h1:3v93+mbWn/v3xzN+31nwkJfrEpAUwp+BagBSZWx+TP8= +github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4= +github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= +github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= +github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cockroachdb/datadriven v1.0.3-0.20230413201302-be42291fc80f h1:otljaYPt5hWxV3MUfO5dFPFiOXg9CyG5/kCfayTqsJ4= +github.com/cockroachdb/datadriven v1.0.3-0.20230413201302-be42291fc80f/go.mod h1:a9RdTaap04u637JoCzcUoIcDmvwSUtcUFtT/C3kJlTU= +github.com/cockroachdb/errors v1.11.3 h1:5bA+k2Y6r+oz/6Z/RFlNeVCesGARKuC6YymtcDrbC/I= +github.com/cockroachdb/errors v1.11.3/go.mod h1:m4UIW4CDjx+R5cybPsNrRbreomiFqt8o1h1wUVazSd8= +github.com/cockroachdb/fifo v0.0.0-20240606204812-0bbfbd93a7ce h1:giXvy4KSc/6g/esnpM7Geqxka4WSqI1SZc7sMJFd3y4= +github.com/cockroachdb/fifo v0.0.0-20240606204812-0bbfbd93a7ce/go.mod h1:9/y3cnZ5GKakj/H4y9r9GTjCvAFta7KLgSHPJJYc52M= +github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b h1:r6VH0faHjZeQy818SGhaone5OnYfxFR/+AzdY3sf5aE= +github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs= +github.com/cockroachdb/pebble v1.1.2 h1:CUh2IPtR4swHlEj48Rhfzw6l/d0qA31fItcIszQVIsA= +github.com/cockroachdb/pebble v1.1.2/go.mod h1:4exszw1r40423ZsmkG/09AFEG83I0uDgfujJdbL6kYU= +github.com/cockroachdb/redact v1.1.5 h1:u1PMllDkdFfPWaNGMyLD1+so+aq3uUItthCFqzwPJ30= +github.com/cockroachdb/redact v1.1.5/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg= +github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 h1:zuQyyAKVxetITBuuhv3BI9cMrmStnpT18zmgmTxunpo= +github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06/go.mod h1:7nc4anLGjupUW/PeY5qiNYsdNXj7zopG+eqsS7To5IQ= +github.com/cometbft/cometbft v1.0.0-rc1.0.20240908111210-ab0be101882f h1:rPWKqyc+CeuddICqlqptf+3NPE8exbC9SOGuDPTEN3k= +github.com/cometbft/cometbft v1.0.0-rc1.0.20240908111210-ab0be101882f/go.mod h1:MqZ5E5jLU1JdP10FSRXhItpm+GdHMbW7Myv3UARLxqg= +github.com/cometbft/cometbft-db v0.15.0 h1:VLtsRt8udD4jHCyjvrsTBpgz83qne5hnL245AcPJVRk= +github.com/cometbft/cometbft-db v0.15.0/go.mod h1:EBrFs1GDRiTqrWXYi4v90Awf/gcdD5ExzdPbg4X8+mk= +github.com/cometbft/cometbft/api v1.0.0-rc.1 h1:GtdXwDGlqwHYs16A4egjwylfYOMYyEacLBrs3Zvpt7g= +github.com/cometbft/cometbft/api v1.0.0-rc.1/go.mod h1:NDFKiBBD8HJC6QQLAoUI99YhsiRZtg2+FJWfk6A6m6o= +github.com/containerd/continuity v0.3.0 h1:nisirsYROK15TAMVukJOUyGJjz4BNQJBVsNvAXZJ/eg= +github.com/containerd/continuity v0.3.0/go.mod h1:wJEAIwKOm/pBZuBd0JmeTvnLquTB1Ag8espWhkykbPM= +github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/cosmos/btcutil v1.0.5 h1:t+ZFcX77LpKtDBhjucvnOH8C2l2ioGsBNEQ3jef8xFk= +github.com/cosmos/btcutil v1.0.5/go.mod h1:IyB7iuqZMJlthe2tkIFL33xPyzbFYP0XVdS8P5lUPis= +github.com/cosmos/cosmos-db v1.0.3-0.20240911104526-ddc3f09bfc22 h1:V3WlarcZwlYYt3dUsStxm0FAFXVeEcvgwfmR6upxm5M= +github.com/cosmos/cosmos-db v1.0.3-0.20240911104526-ddc3f09bfc22/go.mod h1:Z8IXcFJ9PqKK6BIsVOB3QXtkKoqUOp1vRvPT39kOXEA= +github.com/cosmos/cosmos-proto v1.0.0-beta.5 h1:eNcayDLpip+zVLRLYafhzLvQlSmyab+RC5W7ZfmxJLA= +github.com/cosmos/cosmos-proto v1.0.0-beta.5/go.mod h1:hQGLpiIUloJBMdQMMWb/4wRApmI9hjHH05nefC0Ojec= +github.com/cosmos/crypto v0.1.2 h1:Yn500sPY+9sKVdhiPUSDtt8JOpBGMB515dOmla4zfls= +github.com/cosmos/crypto v0.1.2/go.mod h1:b6VWz3HczIpBaQPvI7KrbQeF3pXHh0al3T5e0uwMBQw= +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/gogogateway v1.2.0 h1:Ae/OivNhp8DqBi/sh2A8a1D0y638GpL3tkmLQAiKxTE= +github.com/cosmos/gogogateway v1.2.0/go.mod h1:iQpLkGWxYcnCdz5iAdLcRBSw3h7NXeOkZ4GUkT+tbFI= +github.com/cosmos/gogoproto v1.4.2/go.mod h1:cLxOsn1ljAHSV527CHOtaIP91kK6cCrZETRBrkzItWU= +github.com/cosmos/gogoproto v1.7.0 h1:79USr0oyXAbxg3rspGh/m4SWNyoz/GLaAh0QlCe2fro= +github.com/cosmos/gogoproto v1.7.0/go.mod h1:yWChEv5IUEYURQasfyBW5ffkMHR/90hiHgbNgrtp4j0= +github.com/cosmos/iavl v1.3.0 h1:Ezaxt8aPA3kbkhsfyqwenChGLQwHDAIif3tG9x1FMV8= +github.com/cosmos/iavl v1.3.0/go.mod h1:T6SfBcyhulVIY2G/ZtAtQm/QiJvsuhIos52V4dWYk88= +github.com/cosmos/ics23/go v0.11.0 h1:jk5skjT0TqX5e5QJbEnwXIS2yI2vnmLOgpQPeM5RtnU= +github.com/cosmos/ics23/go v0.11.0/go.mod h1:A8OjxPE67hHST4Icw94hOxxFEJMBG031xIGF/JHNIY0= +github.com/cosmos/ledger-cosmos-go v0.13.3 h1:7ehuBGuyIytsXbd4MP43mLeoN2LTOEnk5nvue4rK+yM= +github.com/cosmos/ledger-cosmos-go v0.13.3/go.mod h1:HENcEP+VtahZFw38HZ3+LS3Iv5XV6svsnkk9vdJtLr8= +github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/danieljoos/wincred v1.2.1 h1:dl9cBrupW8+r5250DYkYxocLeZ1Y4vB1kxgtjxw8GQs= +github.com/danieljoos/wincred v1.2.1/go.mod h1:uGaFL9fDn3OLTvzCGulzE+SzjEe5NGlh5FdCcyfPwps= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y= +github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 h1:rpfIENRNNilwHwZeG5+P150SMrnNEcHYvcCuK6dPZSg= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= +github.com/dgraph-io/badger/v4 v4.3.0 h1:lcsCE1/1qrRhqP+zYx6xDZb8n7U+QlwNicpc676Ub40= +github.com/dgraph-io/badger/v4 v4.3.0/go.mod h1:Sc0T595g8zqAQRDf44n+z3wG4BOqLwceaFntt8KPxUM= +github.com/dgraph-io/ristretto v0.1.2-0.20240116140435-c67e07994f91 h1:Pux6+xANi0I7RRo5E1gflI4EZ2yx3BGZ75JkAIvGEOA= +github.com/dgraph-io/ristretto v0.1.2-0.20240116140435-c67e07994f91/go.mod h1:swkazRqnUf1N62d0Nutz7KIj2UKqsm/H8tD0nBJAXqM= +github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 h1:fAjc9m62+UWV/WAFKLNi6ZS0675eEUC9y3AlwSbQu1Y= +github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= +github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= +github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= +github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= +github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= +github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= +github.com/dvsekhvalnov/jose2go v1.6.0 h1:Y9gnSnP4qEI0+/uQkHvFXeD2PLPJeXEL+ySMEA2EjTY= +github.com/dvsekhvalnov/jose2go v1.6.0/go.mod h1:QsHjhyTlD/lAVqn/NSbVZmSCGeDehTB/mPZadG+mhXU= +github.com/emicklei/dot v1.6.2 h1:08GN+DD79cy/tzN6uLCT84+2Wk9u+wvqP+Hkx/dIR8A= +github.com/emicklei/dot v1.6.2/go.mod h1:DeV7GvQtIw4h2u73RKBkkFdvVAz0D9fzeJrgPW6gy/s= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= +github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= +github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4= +github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI= +github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= +github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= +github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= +github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= +github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= +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/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= +github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= +github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= +github.com/getsentry/sentry-go v0.27.0 h1:Pv98CIbtB3LkMWmXi4Joa5OOcwbmnX88sF5qbK3r3Ps= +github.com/getsentry/sentry-go v0.27.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= +github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= +github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.13.0 h1:OoneCcHKHQ03LfBpoQCUfCluwd2Vt3ohz+kvbJneZAU= +github.com/go-kit/kit v0.13.0/go.mod h1:phqEHMMUbyrCFCTgH48JueqrM3md2HcAZ8N3XE4FKDg= +github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= +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= +github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= +github.com/go-logfmt/logfmt v0.6.0 h1:wGYYu3uicYdqXVgoYbvnkrPVXkuLM1p1ifugDMEdRi4= +github.com/go-logfmt/logfmt v0.6.0/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= +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= +github.com/gogo/googleapis v1.4.1-0.20201022092350-68b0159b7869/go.mod h1:5YRNX2z1oM5gXdAkurHa942MDgEJyk02w4OecKY87+c= +github.com/gogo/googleapis v1.4.1 h1:1Yx4Myt7BxzvUr5ldGSbwYiZG6t9wGBZ+8/fX3Wvtq0= +github.com/gogo/googleapis v1.4.1/go.mod h1:2lpHqI5OcWCtVElxXnPt+s8oJvMpySlOyM6xDCrzib4= +github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= +github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a1/R87v0= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +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/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= +github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg= +github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= +github.com/google/flatbuffers v2.0.8+incompatible h1:ivUb1cGomAB101ZM1T0nOiWz9pSrTMoa9+EiY7igmkM= +github.com/google/flatbuffers v2.0.8+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= +github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +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-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gorilla/handlers v1.5.2 h1:cLTUSsNkgcwhgRqvCNmdbRWG0A3N4F+M2nWKdScwyEE= +github.com/gorilla/handlers v1.5.2/go.mod h1:dX+xVpaxdSw+q0Qek8SSsl3dfMk3jNddUkMzo0GtH0w= +github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= +github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= +github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= +github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 h1:UH//fgunKIs4JdUbpDl1VZCDaL56wXCB/5+wF6uHfaI= +github.com/grpc-ecosystem/go-grpc-middleware v1.4.0/go.mod h1:g5qyo/la0ALbONm6Vbp88Yd8NsDy6rZz+RcrMPxvld8= +github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= +github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c h1:6rhixN/i8ZofjG1Y75iExal34USq5p+wiN1tpie8IrU= +github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c/go.mod h1:NMPJylDgVpX0MLRlPy15sqSwOFv/U1GZ2m21JhFfek0= +github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k= +github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= +github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJFeZnpfm2KLowc= +github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-metrics v0.5.3 h1:M5uADWMOGCTUNU1YuC4hfknOeHNaX54LDm4oYSucoNE= +github.com/hashicorp/go-metrics v0.5.3/go.mod h1:KEjodfebIOuBYSAe/bHTm+HChmKSxAOXPBieMLYozDE= +github.com/hashicorp/go-plugin v1.6.1 h1:P7MR2UP6gNKGPp+y7EZw2kOiq4IR9WiqLvp0XOsVdwI= +github.com/hashicorp/go-plugin v1.6.1/go.mod h1:XPHFku2tFo3o3QKFgSYo+cghcUhw1NA1hZyMK0PWAw0= +github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= +github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.1 h1:fv1ep09latC32wFoVwnqcnKJGnMSdBanPczbHAYm1BE= +github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c= +github.com/hashicorp/golang-lru v1.0.2/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= +github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= +github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE= +github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ= +github.com/hdevalence/ed25519consensus v0.2.0 h1:37ICyZqdyj0lAZ8P4D1d1id3HqbbG1N3iBb1Tb4rdcU= +github.com/hdevalence/ed25519consensus v0.2.0/go.mod h1:w3BHWjwJbFU29IRHL1Iqkw3sus+7FctEyM4RqDxYNzo= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/huandu/go-assert v1.1.5 h1:fjemmA7sSfYHJD7CUqs9qTwwfdNAx7/j2/ZlHXzNB3c= +github.com/huandu/go-assert v1.1.5/go.mod h1:yOLvuqZwmcHIC5rIzrBhT7D3Q9c3GFnd0JrPVhn/06U= +github.com/huandu/skiplist v1.2.1 h1:dTi93MgjwErA/8idWTzIw4Y1kZsMWx35fmI2c8Rij7w= +github.com/huandu/skiplist v1.2.1/go.mod h1:7v3iFjLcSAzO4fN5B8dvebvo/qsfumiLiDXMrPiHF9w= +github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI= +github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= +github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= +github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/jhump/protoreflect v1.17.0 h1:qOEr613fac2lOuTgWN4tPAtLL7fUSbuJL5X5XumQh94= +github.com/jhump/protoreflect v1.17.0/go.mod h1:h9+vUUL38jiBzck8ck+6G/aeMX8Z4QUY/NiJPwPNi+8= +github.com/jmhodges/levigo v1.0.0 h1:q5EC36kV79HWeTBWsod3mG11EgStG3qArTKcvlksN1U= +github.com/jmhodges/levigo v1.0.0/go.mod h1:Q6Qx+uH3RAqyK4rFQroq9RL7mdkABMcfhEI+nNuzMJQ= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= +github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= +github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +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.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +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= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= +github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/linxGnu/grocksdb v1.9.3 h1:s1cbPcOd0cU2SKXRG1nEqCOWYAELQjdqg3RVI2MH9ik= +github.com/linxGnu/grocksdb v1.9.3/go.mod h1:QYiYypR2d4v63Wj1adOOfzglnoII0gLj3PNh4fZkcFA= +github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= +github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= +github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +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/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/minio/highwayhash v1.0.3 h1:kbnuUMoHYyVl7szWjSxJnxw11k2U709jqFPPmIUyD6Q= +github.com/minio/highwayhash v1.0.3/go.mod h1:GGYsuwP/fPD6Y9hMiXuapVvlIUEhFhMTh0rxU3ik1LQ= +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/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/mtibben/percent v0.2.1 h1:5gssi8Nqo8QU/r2pynCm+hBQHpkB/uNK7BJCFogWdzs= +github.com/mtibben/percent v0.2.1/go.mod h1:KG9uO+SZkUp+VkRHsCdYQV3XSZrrSpR3O9ibNBTZrns= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= +github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= +github.com/oasisprotocol/curve25519-voi v0.0.0-20230904125328-1f23a7beb09a h1:dlRvE5fWabOchtH7znfiFCcOvmIYgOeAS5ifBXBlh9Q= +github.com/oasisprotocol/curve25519-voi v0.0.0-20230904125328-1f23a7beb09a/go.mod h1:hVoHR2EVESiICEMbg137etN/Lx+lSrHPTD39Z/uE+2s= +github.com/oklog/run v1.1.0 h1:GEenZ1cK0+q0+wsJew9qUg/DyD8k3JzYsZAi5gYi2mA= +github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DVU= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= +github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= +github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= +github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= +github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= +github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= +github.com/onsi/gomega v1.28.1 h1:MijcGUbfYuznzK/5R4CPNoUP/9Xvuo20sXfEm6XxoTA= +github.com/onsi/gomega v1.28.1/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ= +github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= +github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= +github.com/opencontainers/image-spec v1.1.0-rc5 h1:Ygwkfw9bpDvs+c9E34SdgGOj41dX/cbdlwvlWt0pnFI= +github.com/opencontainers/image-spec v1.1.0-rc5/go.mod h1:X4pATf0uXsnn3g5aiGIsVnJBR4mxhKzfwmvK/B2NTm8= +github.com/opencontainers/runc v1.1.12 h1:BOIssBaW1La0/qbNZHXOOa71dZfZEQOzW7dqQf3phss= +github.com/opencontainers/runc v1.1.12/go.mod h1:S+lQwSfncpBha7XTy/5lBwWgm5+y5Ma/O44Ekby9FK8= +github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/ory/dockertest v3.3.5+incompatible h1:iLLK6SQwIhcbrG783Dghaaa3WPzGc+4Emza6EbVUUGA= +github.com/ory/dockertest v3.3.5+incompatible/go.mod h1:1vX4m9wsvi00u5bseYwXaSnhNrne+V0E6LAcBILJdPs= +github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY= +github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M= +github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc= +github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 h1:Dx7Ovyv/SFnMFw3fD4oEoeorXc6saIiQ23LrGLth0Gw= +github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4= +github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4= +github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8= +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= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= +github.com/prometheus/client_golang v1.20.4 h1:Tgh3Yr67PaOv/uTqloMsCEdeuFTatm5zIq5+qNN23vI= +github.com/prometheus/client_golang v1.20.4/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= +github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= +github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= +github.com/prometheus/common v0.60.0 h1:+V9PAREWNvJMAuJ1x1BaWl9dewMW4YrHZQbx0sJNllA= +github.com/prometheus/common v0.60.0/go.mod h1:h0LYf1R1deLSKtD4Vdg8gy4RuOvENW2J/h19V5NADQw= +github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/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.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= +github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= +github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM= +github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= +github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= +github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= +github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= +github.com/rs/cors v1.11.0 h1:0B9GE/r9Bc2UxRMMtymBkHTenPkHDv0CW4Y98GBY+po= +github.com/rs/cors v1.11.0/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= +github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= +github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8= +github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ= +github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4= +github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= +github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= +github.com/sasha-s/go-deadlock v0.3.5 h1:tNCOEEDG6tBqrNDOX35j/7hL5FcFViG6awUGROb2NsU= +github.com/sasha-s/go-deadlock v0.3.5/go.mod h1:bugP6EGbdGYObIlx7pUZtWqlvo8k9H6vCBBsiChJQ5U= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= +github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= +github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= +github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= +github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= +github.com/spf13/cast v1.7.0 h1:ntdiHjuueXFgm5nzDRdOS4yfT43P5Fnud6DH50rz/7w= +github.com/spf13/cast v1.7.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= +github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= +github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI= +github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+Ntkg= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +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.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= +github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= +github.com/supranational/blst v0.3.13 h1:AYeSxdOMacwu7FBmpfloBz5pbFXDmJL33RuwnKtmTjk= +github.com/supranational/blst v0.3.13/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= +github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d h1:vfofYNRScrDdvS342BElfbETmL1Aiz3i2t0zfRj16Hs= +github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d/go.mod h1:RRCYJbIwD5jmqPI9XoAFR0OcDxqUctll6zUj/+B4S48= +github.com/tendermint/go-amino v0.16.0 h1:GyhmgQKvqF82e2oZeuMSp9JTN0N09emoSZlb2lyGa2E= +github.com/tendermint/go-amino v0.16.0/go.mod h1:TQU0M1i/ImAo+tYpZi73AU3V/dKeCoMC9Sphe2ZwGME= +github.com/tidwall/btree v1.7.0 h1:L1fkJH/AuEh5zBnnBbmTwQ5Lt+bRJ5A8EWecslvo9iI= +github.com/tidwall/btree v1.7.0/go.mod h1:twD9XRA5jj9VUQGELzDO4HPQTNJsoWWfYEL+EUQ2cKY= +github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/zondax/hid v0.9.2 h1:WCJFnEDMiqGF64nlZz28E9qLVZ0KSJ7xpc5DLEyma2U= +github.com/zondax/hid v0.9.2/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM= +github.com/zondax/ledger-go v0.14.3 h1:wEpJt2CEcBJ428md/5MgSLsXLBos98sBOyxNmCjfUCw= +github.com/zondax/ledger-go v0.14.3/go.mod h1:IKKaoxupuB43g4NxeQmbLXv7T9AlQyie1UpHb342ycI= +gitlab.com/yawning/secp256k1-voi v0.0.0-20230925100816-f2616030848b h1:CzigHMRySiX3drau9C6Q5CAbNIApmLdat5jPMqChvDA= +gitlab.com/yawning/secp256k1-voi v0.0.0-20230925100816-f2616030848b/go.mod h1:/y/V339mxv2sZmYYR64O07VuCpdNZqCTwO8ZcouTMI8= +gitlab.com/yawning/tuplehash v0.0.0-20230713102510-df83abbf9a02 h1:qwDnMxjkyLmAFgcfgTnfJrmYKWhHnci3GjDqcZp1M3Q= +gitlab.com/yawning/tuplehash v0.0.0-20230713102510-df83abbf9a02/go.mod h1:JTnUj0mpYiAsuZLmKjTx/ex3AtMowcCgnE7YNyCEP0I= +go.etcd.io/bbolt v1.4.0-alpha.0.0.20240404170359-43604f3112c5 h1:qxen9oVGzDdIRP6ejyAJc760RwW4SnVDiTYTzwnXuxo= +go.etcd.io/bbolt v1.4.0-alpha.0.0.20240404170359-43604f3112c5/go.mod h1:eW0HG9/oHQhvRCvb1/pIXW4cOvtDqeQK+XSi3TnwaXY= +go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= +go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= +go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= +go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= +go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU= +go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc= +go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= +go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= +go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A= +golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20240531132922-fd00a4e0eefc h1:O9NuF4s+E/PvMIy+9IUZB9znFwUIXEWSstNjek6VpVg= +golang.org/x/exp v0.0.0-20240531132922-fd00a4e0eefc/go.mod h1:XtvwrStGgqGPLc4cjQfWqZHG1YFdYs6swckp8vpsjnc= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= +golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +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= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= +golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo= +golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +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= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= +golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +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= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/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-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-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/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-20220315194320-039c03cc5b86/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-20220503163025-988cb79eb6c6/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-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= +golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +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.24.0 h1:Mh5cbb+Zk2hqqXNO7S1iTjEphVL+jb8ZWaqh/g+JWkM= +golang.org/x/term v0.24.0/go.mod h1:lOBK/LVxemqiMij05LGJ0tzNr8xlmwBRJ81PX6wVLH8= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/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.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= +golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg= +golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= +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= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20220314164441-57ef72a4c106/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E= +google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de h1:F6qOa9AZTYJXOUEr4jDysRDLrm4PHePlge4v4TGAlxY= +google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:VUhTRKeHn9wwcdrk73nvdC9gF178Tzhmt/qyaFcPLSo= +google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 h1:wKguEg1hsxI2/L3hUYrpo1RVi48K+uTyzKqprwLXsb8= +google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142/go.mod h1:d6be+8HhtEtucleCbxpPW9PA9XwISACu8nvpPqF0BVo= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f h1:cUMEy+8oS78BWIH9OWazBkzbr090Od9tWBNtZHkOhf0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= +google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= +google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= +google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= +google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= +google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E= +google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= +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= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +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.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= +google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= +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= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU= +gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +pgregory.net/rapid v1.1.0 h1:CMa0sjHSru3puNx+J0MIAuiiEV4N0qj8/cMWGBBCsjw= +pgregory.net/rapid v1.1.0/go.mod h1:PY5XlDGj0+V1FCq0o192FdRhpKHGTRIWBgqjDBTrq04= +sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= +sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= diff --git a/x/accounts/defaults/base/v1/base.pb.go b/x/accounts/defaults/base/v1/base.pb.go index cc9078c736e1..dd8c44aaff2b 100644 --- a/x/accounts/defaults/base/v1/base.pb.go +++ b/x/accounts/defaults/base/v1/base.pb.go @@ -27,6 +27,9 @@ const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package type MsgInit struct { // pub_key defines a pubkey for the account arbitrary encapsulated. PubKey *any.Any `protobuf:"bytes,1,opt,name=pub_key,json=pubKey,proto3" json:"pub_key,omitempty"` + // init_sequence defines the initial sequence of the account. + // Defaults to zero if not set. + InitSequence uint64 `protobuf:"varint,2,opt,name=init_sequence,json=initSequence,proto3" json:"init_sequence,omitempty"` } func (m *MsgInit) Reset() { *m = MsgInit{} } @@ -69,6 +72,13 @@ func (m *MsgInit) GetPubKey() *any.Any { return nil } +func (m *MsgInit) GetInitSequence() uint64 { + if m != nil { + return m.InitSequence + } + return 0 +} + // MsgInitResponse is the response returned after base account initialization. // This is empty. type MsgInitResponse struct { @@ -372,26 +382,28 @@ func init() { } var fileDescriptor_7c860870b5ed6dc2 = []byte{ - // 303 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x91, 0xcf, 0x4a, 0xc3, 0x40, - 0x10, 0xc6, 0x1b, 0x90, 0x56, 0xa7, 0x94, 0x62, 0xb4, 0xa8, 0x3d, 0x2c, 0x65, 0x4f, 0x05, 0x71, - 0x97, 0x5a, 0x0f, 0x5e, 0x2d, 0x7a, 0x10, 0x29, 0x68, 0x7a, 0xf3, 0x52, 0x92, 0x74, 0x1a, 0x4a, - 0xeb, 0x6e, 0xec, 0x66, 0x1b, 0xf3, 0x16, 0x3e, 0x96, 0xc7, 0x1e, 0x3d, 0x4a, 0xf2, 0x22, 0xc2, - 0xe6, 0x0f, 0xf6, 0x20, 0xe8, 0x69, 0x99, 0xe1, 0xf7, 0xfb, 0x06, 0xf6, 0x83, 0x73, 0x5f, 0xaa, - 0x17, 0xa9, 0xb8, 0xeb, 0xfb, 0x52, 0x8b, 0x48, 0xf1, 0x19, 0xce, 0x5d, 0xbd, 0x8a, 0x14, 0xf7, - 0x5c, 0x85, 0x7c, 0x33, 0x30, 0x2f, 0x0b, 0xd7, 0x32, 0x92, 0x76, 0x2f, 0x87, 0x59, 0x09, 0xb3, - 0x12, 0x66, 0x06, 0xda, 0x0c, 0xba, 0x67, 0x81, 0x94, 0xc1, 0x0a, 0xb9, 0xe1, 0x3d, 0x3d, 0xe7, - 0xae, 0x48, 0x72, 0x99, 0x5e, 0x43, 0x63, 0xac, 0x82, 0x7b, 0xb1, 0x88, 0xec, 0x0b, 0x68, 0x84, - 0xda, 0x9b, 0x2e, 0x31, 0x39, 0xb5, 0x7a, 0x56, 0xbf, 0x79, 0x79, 0xcc, 0x72, 0x8f, 0x95, 0x1e, - 0xbb, 0x11, 0x89, 0x53, 0x0f, 0xb5, 0xf7, 0x80, 0x09, 0x3d, 0x84, 0x76, 0x61, 0x3a, 0xa8, 0x42, - 0x29, 0x14, 0xd2, 0x3b, 0x68, 0x8d, 0x55, 0x30, 0x89, 0xdd, 0xf0, 0xd1, 0x30, 0xf6, 0x15, 0x34, - 0x05, 0xc6, 0xd3, 0xbf, 0xc4, 0x1e, 0x08, 0x8c, 0x73, 0x8b, 0x9e, 0x40, 0x67, 0x27, 0xa6, 0xca, - 0x6f, 0x43, 0xeb, 0x49, 0xe3, 0x3a, 0x99, 0xe0, 0xab, 0x46, 0xe1, 0x23, 0x1d, 0x42, 0x67, 0x67, - 0x51, 0x92, 0x76, 0x17, 0xf6, 0x55, 0xb1, 0x33, 0x57, 0xf7, 0x9c, 0x6a, 0xa6, 0x2d, 0x68, 0x1a, - 0xa9, 0xb8, 0x76, 0x0b, 0x47, 0x3f, 0xc6, 0x2a, 0xe1, 0x7f, 0xbf, 0x31, 0x1a, 0x7d, 0xa4, 0xc4, - 0xda, 0xa6, 0xc4, 0xfa, 0x4a, 0x89, 0xf5, 0x9e, 0x91, 0xda, 0x36, 0x23, 0xb5, 0xcf, 0x8c, 0xd4, - 0x9e, 0xfb, 0x79, 0x3d, 0x6a, 0xb6, 0x64, 0x0b, 0xc9, 0xdf, 0x7e, 0xef, 0xd4, 0xab, 0x9b, 0xe4, - 0xe1, 0x77, 0x00, 0x00, 0x00, 0xff, 0xff, 0x8f, 0xe1, 0xb2, 0xd8, 0xfe, 0x01, 0x00, 0x00, + // 323 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x91, 0xc1, 0x4a, 0xf3, 0x40, + 0x10, 0xc7, 0xbb, 0x1f, 0x1f, 0xad, 0x4e, 0x0d, 0xc5, 0x68, 0xb1, 0xf6, 0x10, 0x4a, 0xbc, 0x14, + 0xc4, 0x5d, 0x6a, 0x7d, 0x01, 0x8b, 0x1e, 0x44, 0x0a, 0xda, 0xde, 0x04, 0x29, 0x49, 0x3a, 0x0d, + 0xa1, 0x75, 0x37, 0x76, 0xb3, 0xad, 0x79, 0x0b, 0x1f, 0xcb, 0x63, 0x8f, 0x1e, 0xa5, 0x7d, 0x11, + 0x71, 0x37, 0x09, 0xf6, 0x20, 0xe8, 0x69, 0x99, 0xe1, 0xf7, 0xff, 0xcd, 0xb0, 0x03, 0xa7, 0x81, + 0x90, 0x4f, 0x42, 0x32, 0x2f, 0x08, 0x84, 0xe2, 0x89, 0x64, 0x63, 0x9c, 0x78, 0x6a, 0x96, 0x48, + 0xe6, 0x7b, 0x12, 0xd9, 0xa2, 0xa3, 0x5f, 0x1a, 0xcf, 0x45, 0x22, 0xec, 0x96, 0x81, 0x69, 0x0e, + 0xd3, 0x1c, 0xa6, 0x1a, 0x5a, 0x74, 0x9a, 0xc7, 0xa1, 0x10, 0xe1, 0x0c, 0x99, 0xe6, 0x7d, 0x35, + 0x61, 0x1e, 0x4f, 0x4d, 0xd8, 0x7d, 0x84, 0x4a, 0x5f, 0x86, 0x37, 0x3c, 0x4a, 0xec, 0x33, 0xa8, + 0xc4, 0xca, 0x1f, 0x4d, 0x31, 0x6d, 0x90, 0x16, 0x69, 0x57, 0xcf, 0x0f, 0xa9, 0xc9, 0xd1, 0x3c, + 0x47, 0x2f, 0x79, 0x3a, 0x28, 0xc7, 0xca, 0xbf, 0xc5, 0xd4, 0x3e, 0x01, 0x2b, 0xe2, 0x51, 0x32, + 0x92, 0xf8, 0xac, 0x90, 0x07, 0xd8, 0xf8, 0xd7, 0x22, 0xed, 0xff, 0x83, 0xbd, 0xaf, 0xe6, 0x30, + 0xeb, 0xb9, 0xfb, 0x50, 0xcb, 0xf4, 0x03, 0x94, 0xb1, 0xe0, 0x12, 0xdd, 0x6b, 0xb0, 0xfa, 0x32, + 0x1c, 0x2e, 0xbd, 0xf8, 0xce, 0x88, 0x2e, 0xa0, 0xca, 0x71, 0x39, 0xfa, 0xcd, 0xec, 0x5d, 0x8e, + 0x4b, 0x93, 0x72, 0x8f, 0xa0, 0xbe, 0xa5, 0x29, 0xfc, 0x35, 0xb0, 0xee, 0x15, 0xce, 0xd3, 0x62, + 0x87, 0x2e, 0xd4, 0xb7, 0x1a, 0x39, 0x69, 0x37, 0x61, 0xa7, 0x58, 0x9e, 0xe8, 0xe5, 0x8b, 0xda, + 0xb5, 0xa0, 0xaa, 0x43, 0xd9, 0xb4, 0x2b, 0x38, 0xf8, 0x56, 0x16, 0x86, 0xbf, 0x7d, 0x59, 0xaf, + 0xf7, 0xb6, 0x76, 0xc8, 0x6a, 0xed, 0x90, 0x8f, 0xb5, 0x43, 0x5e, 0x37, 0x4e, 0x69, 0xb5, 0x71, + 0x4a, 0xef, 0x1b, 0xa7, 0xf4, 0xd0, 0x36, 0x37, 0x94, 0xe3, 0x29, 0x8d, 0x04, 0x7b, 0xf9, 0xf9, + 0xf0, 0x7e, 0x59, 0x9b, 0xbb, 0x9f, 0x01, 0x00, 0x00, 0xff, 0xff, 0x30, 0xaf, 0x2e, 0x20, 0x23, + 0x02, 0x00, 0x00, } func (m *MsgInit) Marshal() (dAtA []byte, err error) { @@ -414,6 +426,11 @@ func (m *MsgInit) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if m.InitSequence != 0 { + i = encodeVarintBase(dAtA, i, uint64(m.InitSequence)) + i-- + dAtA[i] = 0x10 + } if m.PubKey != nil { { size, err := m.PubKey.MarshalToSizedBuffer(dAtA[:i]) @@ -640,6 +657,9 @@ func (m *MsgInit) Size() (n int) { l = m.PubKey.Size() n += 1 + l + sovBase(uint64(l)) } + if m.InitSequence != 0 { + n += 1 + sovBase(uint64(m.InitSequence)) + } return n } @@ -788,6 +808,25 @@ func (m *MsgInit) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field InitSequence", wireType) + } + m.InitSequence = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowBase + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.InitSequence |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } default: iNdEx = preIndex skippy, err := skipBase(dAtA[iNdEx:]) diff --git a/x/accounts/defaults/lockup/depinject/depinject.go b/x/accounts/defaults/lockup/depinject/depinject.go new file mode 100644 index 000000000000..df26d6ce78aa --- /dev/null +++ b/x/accounts/defaults/lockup/depinject/depinject.go @@ -0,0 +1,31 @@ +package lockupdepinject + +import ( + "cosmossdk.io/x/accounts/accountstd" + "cosmossdk.io/x/accounts/defaults/lockup" +) + +func ProvideAllLockupAccounts() []accountstd.DepinjectAccount { + return []accountstd.DepinjectAccount{ + ProvidePeriodicLockingAccount(), + ProvideContinuousLockingAccount(), + ProvidePermanentLockingAccount(), + ProvideDelayedLockingAccount(), + } +} + +func ProvideContinuousLockingAccount() accountstd.DepinjectAccount { + return accountstd.DIAccount(lockup.CONTINUOUS_LOCKING_ACCOUNT, lockup.NewContinuousLockingAccount) +} + +func ProvidePeriodicLockingAccount() accountstd.DepinjectAccount { + return accountstd.DIAccount(lockup.PERIODIC_LOCKING_ACCOUNT, lockup.NewPeriodicLockingAccount) +} + +func ProvideDelayedLockingAccount() accountstd.DepinjectAccount { + return accountstd.DIAccount(lockup.DELAYED_LOCKING_ACCOUNT, lockup.NewDelayedLockingAccount) +} + +func ProvidePermanentLockingAccount() accountstd.DepinjectAccount { + return accountstd.DIAccount(lockup.PERMANENT_LOCKING_ACCOUNT, lockup.NewPermanentLockingAccount) +} diff --git a/x/accounts/defaults/lockup/go.mod b/x/accounts/defaults/lockup/go.mod index e191695a75c2..2f66fafe70f0 100644 --- a/x/accounts/defaults/lockup/go.mod +++ b/x/accounts/defaults/lockup/go.mod @@ -4,7 +4,7 @@ go 1.23.1 require ( cosmossdk.io/collections v0.4.0 - cosmossdk.io/core v1.0.0-alpha.2 + cosmossdk.io/core v1.0.0-alpha.4 cosmossdk.io/x/accounts v0.0.0-20240226161501-23359a0b6d91 cosmossdk.io/x/bank v0.0.0-20240226161501-23359a0b6d91 cosmossdk.io/x/distribution v0.0.0-00010101000000-000000000000 @@ -16,13 +16,13 @@ require ( require ( buf.build/gen/go/cometbft/cometbft/protocolbuffers/go v1.34.2-20240701160653-fedbb9acfd2f.2 // indirect buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.34.2-20240130113600-88ef6483f90f.2 // indirect - cosmossdk.io/api v0.7.5 // indirect - cosmossdk.io/core/testing v0.0.0-00010101000000-000000000000 // indirect + cosmossdk.io/api v0.7.6 // indirect + cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29 // indirect cosmossdk.io/depinject v1.0.0 // indirect cosmossdk.io/errors v1.0.1 cosmossdk.io/log v1.4.1 cosmossdk.io/math v1.3.0 - cosmossdk.io/schema v0.2.0 // indirect + cosmossdk.io/schema v0.3.1-0.20240930054013-7c6e0388a3f9 // indirect cosmossdk.io/store v1.1.1-0.20240418092142-896cdf1971bc // indirect cosmossdk.io/x/tx v0.13.3 // indirect filippo.io/edwards25519 v1.1.0 // indirect @@ -96,9 +96,9 @@ require ( github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/client_golang v1.20.3 // indirect + github.com/prometheus/client_golang v1.20.4 // indirect github.com/prometheus/client_model v0.6.1 // indirect - github.com/prometheus/common v0.59.1 // indirect + github.com/prometheus/common v0.60.0 // indirect github.com/prometheus/procfs v0.15.1 // indirect github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect github.com/rogpeppe/go-internal v1.12.0 // indirect @@ -133,9 +133,9 @@ require ( golang.org/x/term v0.24.0 // indirect golang.org/x/text v0.18.0 // indirect google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect - google.golang.org/grpc v1.66.2 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f // indirect + google.golang.org/grpc v1.67.1 // indirect google.golang.org/protobuf v1.34.2 gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect @@ -149,15 +149,10 @@ replace github.com/cosmos/cosmos-sdk => ../../../../. replace ( cosmossdk.io/api => ../../../../api cosmossdk.io/collections => ../../../../collections // TODO tag new collections ASAP - cosmossdk.io/core/testing => ../../../../core/testing cosmossdk.io/store => ../../../../store cosmossdk.io/x/accounts => ../../. cosmossdk.io/x/bank => ../../../bank - cosmossdk.io/x/consensus => ../../../consensus cosmossdk.io/x/distribution => ../../../distribution - cosmossdk.io/x/gov => ../../../gov - cosmossdk.io/x/mint => ../../../mint - cosmossdk.io/x/protocolpool => ../../../protocolpool - cosmossdk.io/x/slashing => ../../../slashing cosmossdk.io/x/staking => ../../../staking + cosmossdk.io/x/tx => ../../../tx ) diff --git a/x/accounts/defaults/lockup/go.sum b/x/accounts/defaults/lockup/go.sum index 9e0736060c2e..3609dca29bfb 100644 --- a/x/accounts/defaults/lockup/go.sum +++ b/x/accounts/defaults/lockup/go.sum @@ -4,8 +4,10 @@ buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.34.2-20240130113600-88e buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.34.2-20240130113600-88ef6483f90f.2/go.mod h1:HqcXMSa5qnNuakaMUo+hWhF51mKbcrZxGl9Vp5EeJXc= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cosmossdk.io/core v1.0.0-alpha.2 h1:epU0Xwces4Rgl5bMhHHkXGaGDcyucNGlC/JDH+Suckg= -cosmossdk.io/core v1.0.0-alpha.2/go.mod h1:abgLjeFLhtuKIYZWSPlVUgQBrKObO7ULV35KYfexE90= +cosmossdk.io/core v1.0.0-alpha.4 h1:9iuroT9ejDYETCsGkzkvs/wAY/5UFl7nCIINFRxyMJY= +cosmossdk.io/core v1.0.0-alpha.4/go.mod h1:3u9cWq1FAVtiiCrDPpo4LhR+9V6k/ycSG4/Y/tREWCY= +cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29 h1:NxxUo0GMJUbIuVg0R70e3cbn9eFTEuMr7ev1AFvypdY= +cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29/go.mod h1:8s2tPeJtSiQuoyPmr2Ag7meikonISO4Fv4MoO8+ORrs= cosmossdk.io/depinject v1.0.0 h1:dQaTu6+O6askNXO06+jyeUAnF2/ssKwrrszP9t5q050= cosmossdk.io/depinject v1.0.0/go.mod h1:zxK/h3HgHoA/eJVtiSsoaRaRA2D5U4cJ5thIG4ssbB8= cosmossdk.io/errors v1.0.1 h1:bzu+Kcr0kS/1DuPBtUFdWjzLqyUuCiyHjyJB6srBV/0= @@ -14,10 +16,8 @@ cosmossdk.io/log v1.4.1 h1:wKdjfDRbDyZRuWa8M+9nuvpVYxrEOwbD/CA8hvhU8QM= cosmossdk.io/log v1.4.1/go.mod h1:k08v0Pyq+gCP6phvdI6RCGhLf/r425UT6Rk/m+o74rU= cosmossdk.io/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE= cosmossdk.io/math v1.3.0/go.mod h1:vnRTxewy+M7BtXBNFybkuhSH4WfedVAAnERHgVFhp3k= -cosmossdk.io/schema v0.2.0 h1:UH5CR1DqUq8yP+5Np8PbvG4YX0zAUsTN2Qk6yThmfMk= -cosmossdk.io/schema v0.2.0/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= -cosmossdk.io/x/tx v0.13.3 h1:Ha4mNaHmxBc6RMun9aKuqul8yHiL78EKJQ8g23Zf73g= -cosmossdk.io/x/tx v0.13.3/go.mod h1:I8xaHv0rhUdIvIdptKIqzYy27+n2+zBVaxO6fscFhys= +cosmossdk.io/schema v0.3.1-0.20240930054013-7c6e0388a3f9 h1:DmOoS/1PeY6Ih0hAVlJ69kLMUrLV+TCbfICrZtB1vdU= +cosmossdk.io/schema v0.3.1-0.20240930054013-7c6e0388a3f9/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMbk2FiG/kXiLl8BRyzTWDw7gX/Hz7Dd5eDMs= @@ -257,8 +257,8 @@ github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbg github.com/hdevalence/ed25519consensus v0.2.0 h1:37ICyZqdyj0lAZ8P4D1d1id3HqbbG1N3iBb1Tb4rdcU= github.com/hdevalence/ed25519consensus v0.2.0/go.mod h1:w3BHWjwJbFU29IRHL1Iqkw3sus+7FctEyM4RqDxYNzo= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/huandu/skiplist v1.2.0 h1:gox56QD77HzSC0w+Ws3MH3iie755GBJU1OER3h5VsYw= -github.com/huandu/skiplist v1.2.0/go.mod h1:7v3iFjLcSAzO4fN5B8dvebvo/qsfumiLiDXMrPiHF9w= +github.com/huandu/skiplist v1.2.1 h1:dTi93MgjwErA/8idWTzIw4Y1kZsMWx35fmI2c8Rij7w= +github.com/huandu/skiplist v1.2.1/go.mod h1:7v3iFjLcSAzO4fN5B8dvebvo/qsfumiLiDXMrPiHF9w= github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI= github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= @@ -349,8 +349,8 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= -github.com/prometheus/client_golang v1.20.3 h1:oPksm4K8B+Vt35tUhw6GbSNSgVlVSBH0qELP/7u83l4= -github.com/prometheus/client_golang v1.20.3/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_golang v1.20.4 h1:Tgh3Yr67PaOv/uTqloMsCEdeuFTatm5zIq5+qNN23vI= +github.com/prometheus/client_golang v1.20.4/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -359,8 +359,8 @@ github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= -github.com/prometheus/common v0.59.1 h1:LXb1quJHWm1P6wq/U824uxYi4Sg0oGvNeUm1z5dJoX0= -github.com/prometheus/common v0.59.1/go.mod h1:GpWM7dewqmVYcd7SmRaiWVe9SSqjf0UrwnYnpEZNuT0= +github.com/prometheus/common v0.60.0 h1:+V9PAREWNvJMAuJ1x1BaWl9dewMW4YrHZQbx0sJNllA= +github.com/prometheus/common v0.60.0/go.mod h1:h0LYf1R1deLSKtD4Vdg8gy4RuOvENW2J/h19V5NADQw= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/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= @@ -553,18 +553,18 @@ google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfG google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de h1:F6qOa9AZTYJXOUEr4jDysRDLrm4PHePlge4v4TGAlxY= google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:VUhTRKeHn9wwcdrk73nvdC9gF178Tzhmt/qyaFcPLSo= -google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 h1:+rdxYoE3E5htTEWIe15GlN6IfvbURM//Jt0mmkmm6ZU= -google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117/go.mod h1:OimBR/bc1wPO9iV4NC2bpyjy3VnAwZh5EBPQdtaE5oo= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:pPJltXNxVzT4pK9yD8vR9X75DaWYYmLGMsEvBfFQZzQ= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= +google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 h1:wKguEg1hsxI2/L3hUYrpo1RVi48K+uTyzKqprwLXsb8= +google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142/go.mod h1:d6be+8HhtEtucleCbxpPW9PA9XwISACu8nvpPqF0BVo= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f h1:cUMEy+8oS78BWIH9OWazBkzbr090Od9tWBNtZHkOhf0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.66.2 h1:3QdXkuq3Bkh7w+ywLdLvM56cmGvQHUMZpiCzt6Rqaoo= -google.golang.org/grpc v1.66.2/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y= +google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E= +google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= 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= diff --git a/x/accounts/defaults/lockup/lockup.go b/x/accounts/defaults/lockup/lockup.go index c6abf92981ac..3ac17fea6133 100644 --- a/x/accounts/defaults/lockup/lockup.go +++ b/x/accounts/defaults/lockup/lockup.go @@ -4,7 +4,6 @@ import ( "bytes" "context" "errors" - "fmt" "maps" "slices" "time" @@ -399,31 +398,22 @@ func (bva *BaseLockup) checkSender(ctx context.Context, sender string) error { } func sendMessage(ctx context.Context, msg proto.Message) ([]*codectypes.Any, error) { - response, err := accountstd.ExecModule(ctx, msg) + asAny, err := accountstd.PackAny(msg) if err != nil { return nil, err } - respAny, err := accountstd.PackAny(response) - if err != nil { - return nil, err - } - - return []*codectypes.Any{respAny}, nil + return accountstd.ExecModuleAnys(ctx, []*codectypes.Any{asAny}) } func getStakingDenom(ctx context.Context) (string, error) { // Query account balance for the sent denom - resp, err := accountstd.QueryModule(ctx, &stakingtypes.QueryParamsRequest{}) + resp, err := accountstd.QueryModule[*stakingtypes.QueryParamsResponse](ctx, &stakingtypes.QueryParamsRequest{}) if err != nil { return "", err } - res, ok := resp.(*stakingtypes.QueryParamsResponse) - if !ok { - return "", fmt.Errorf("unexpected response type: %T", resp) - } - return res.Params.BondDenom, nil + return resp.Params.BondDenom, nil } // TrackDelegation tracks a delegation amount for any given lockup account type @@ -548,17 +538,12 @@ func (bva *BaseLockup) TrackUndelegation(ctx context.Context, amount sdk.Coins) func (bva BaseLockup) getBalance(ctx context.Context, sender, denom string) (*sdk.Coin, error) { // Query account balance for the sent denom - resp, err := accountstd.QueryModule(ctx, &banktypes.QueryBalanceRequest{Address: sender, Denom: denom}) + resp, err := accountstd.QueryModule[*banktypes.QueryBalanceResponse](ctx, &banktypes.QueryBalanceRequest{Address: sender, Denom: denom}) if err != nil { return nil, err } - res, ok := resp.(*banktypes.QueryBalanceResponse) - if !ok { - return nil, fmt.Errorf("unexpected response type: %T", resp) - } - - return res.Balance, nil + return resp.Balance, nil } func (bva BaseLockup) checkTokensSendable(ctx context.Context, sender string, amount, lockedCoins sdk.Coins) error { diff --git a/x/accounts/defaults/lockup/lockup_test.go b/x/accounts/defaults/lockup/lockup_test.go index 67f3cadfbdf4..31c3fda141a3 100644 --- a/x/accounts/defaults/lockup/lockup_test.go +++ b/x/accounts/defaults/lockup/lockup_test.go @@ -53,7 +53,6 @@ func TestInitLockupAccount(t *testing.T) { } for _, test := range testcases { - test := test _, err := baseLockup.Init(ctx, &test.msg) if test.expErr != nil { require.Equal(t, test.expErr, err) diff --git a/x/accounts/defaults/multisig/account.go b/x/accounts/defaults/multisig/account.go index 62dbea15c3ba..e60476b33f6c 100644 --- a/x/accounts/defaults/multisig/account.go +++ b/x/accounts/defaults/multisig/account.go @@ -16,8 +16,6 @@ import ( "github.com/cosmos/cosmos-sdk/codec" ) -var MULTISIG_ACCOUNT = "multisig-account" - var ( MembersPrefix = collections.NewPrefix(0) SequencePrefix = collections.NewPrefix(1) diff --git a/x/accounts/defaults/multisig/depinject/depinject.go b/x/accounts/defaults/multisig/depinject/depinject.go new file mode 100644 index 000000000000..785799b1a3dd --- /dev/null +++ b/x/accounts/defaults/multisig/depinject/depinject.go @@ -0,0 +1,10 @@ +package multisigdepinject + +import ( + "cosmossdk.io/x/accounts/accountstd" + "cosmossdk.io/x/accounts/defaults/multisig" +) + +func ProvideAccount() accountstd.DepinjectAccount { + return accountstd.DIAccount("multisig", multisig.NewAccount) +} diff --git a/x/accounts/defaults/multisig/go.mod b/x/accounts/defaults/multisig/go.mod index a6a2b99bb3c3..3d2600c39a02 100644 --- a/x/accounts/defaults/multisig/go.mod +++ b/x/accounts/defaults/multisig/go.mod @@ -4,7 +4,7 @@ go 1.23.1 require ( cosmossdk.io/collections v0.4.0 - cosmossdk.io/core v1.0.0-alpha.2 + cosmossdk.io/core v1.0.0-alpha.4 cosmossdk.io/math v1.3.0 cosmossdk.io/x/accounts v0.0.0-00010101000000-000000000000 cosmossdk.io/x/bank v0.0.0-20240226161501-23359a0b6d91 @@ -18,12 +18,12 @@ require ( require ( buf.build/gen/go/cometbft/cometbft/protocolbuffers/go v1.34.2-20240701160653-fedbb9acfd2f.2 // indirect buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.34.2-20240130113600-88ef6483f90f.2 // indirect - cosmossdk.io/api v0.7.5 // indirect - cosmossdk.io/core/testing v0.0.0-00010101000000-000000000000 // indirect + cosmossdk.io/api v0.7.6 // indirect + cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29 // indirect cosmossdk.io/depinject v1.0.0 // indirect cosmossdk.io/errors v1.0.1 // indirect cosmossdk.io/log v1.4.1 // indirect - cosmossdk.io/schema v0.2.0 // indirect + cosmossdk.io/schema v0.3.1-0.20240930054013-7c6e0388a3f9 // indirect cosmossdk.io/store v1.1.1-0.20240418092142-896cdf1971bc // indirect cosmossdk.io/x/staking v0.0.0-00010101000000-000000000000 // indirect cosmossdk.io/x/tx v0.13.3 // indirect @@ -95,7 +95,7 @@ require ( github.com/hashicorp/hcl v1.0.0 // indirect github.com/hashicorp/yamux v0.1.1 // indirect github.com/hdevalence/ed25519consensus v0.2.0 // indirect - github.com/huandu/skiplist v1.2.0 // indirect + github.com/huandu/skiplist v1.2.1 // indirect github.com/iancoleman/strcase v0.3.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jmhodges/levigo v1.0.0 // indirect @@ -118,9 +118,9 @@ require ( github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/client_golang v1.20.3 // indirect + github.com/prometheus/client_golang v1.20.4 // indirect github.com/prometheus/client_model v0.6.1 // indirect - github.com/prometheus/common v0.59.1 // indirect + github.com/prometheus/common v0.60.0 // indirect github.com/prometheus/procfs v0.15.1 // indirect github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect github.com/rogpeppe/go-internal v1.12.0 // indirect @@ -157,9 +157,9 @@ require ( golang.org/x/text v0.18.0 // indirect golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect - google.golang.org/grpc v1.66.2 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f // indirect + google.golang.org/grpc v1.67.1 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect gotest.tools/v3 v3.5.1 // indirect @@ -172,15 +172,9 @@ replace github.com/cosmos/cosmos-sdk => ../../../../. replace ( cosmossdk.io/api => ../../../../api cosmossdk.io/collections => ../../../../collections // TODO tag new collections ASAP - cosmossdk.io/core/testing => ../../../../core/testing cosmossdk.io/store => ../../../../store cosmossdk.io/x/accounts => ../../. cosmossdk.io/x/bank => ../../../bank - cosmossdk.io/x/consensus => ../../../consensus - cosmossdk.io/x/gov => ../../../gov - cosmossdk.io/x/mint => ../../../mint - cosmossdk.io/x/protocolpool => ../../../protocolpool - cosmossdk.io/x/slashing => ../../../slashing cosmossdk.io/x/staking => ../../../staking cosmossdk.io/x/tx => ../../../tx ) diff --git a/x/accounts/defaults/multisig/go.sum b/x/accounts/defaults/multisig/go.sum index af04341f3bfc..25dd6bf3bb3f 100644 --- a/x/accounts/defaults/multisig/go.sum +++ b/x/accounts/defaults/multisig/go.sum @@ -4,8 +4,10 @@ buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.34.2-20240130113600-88e buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.34.2-20240130113600-88ef6483f90f.2/go.mod h1:HqcXMSa5qnNuakaMUo+hWhF51mKbcrZxGl9Vp5EeJXc= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cosmossdk.io/core v1.0.0-alpha.2 h1:epU0Xwces4Rgl5bMhHHkXGaGDcyucNGlC/JDH+Suckg= -cosmossdk.io/core v1.0.0-alpha.2/go.mod h1:abgLjeFLhtuKIYZWSPlVUgQBrKObO7ULV35KYfexE90= +cosmossdk.io/core v1.0.0-alpha.4 h1:9iuroT9ejDYETCsGkzkvs/wAY/5UFl7nCIINFRxyMJY= +cosmossdk.io/core v1.0.0-alpha.4/go.mod h1:3u9cWq1FAVtiiCrDPpo4LhR+9V6k/ycSG4/Y/tREWCY= +cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29 h1:NxxUo0GMJUbIuVg0R70e3cbn9eFTEuMr7ev1AFvypdY= +cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29/go.mod h1:8s2tPeJtSiQuoyPmr2Ag7meikonISO4Fv4MoO8+ORrs= cosmossdk.io/depinject v1.0.0 h1:dQaTu6+O6askNXO06+jyeUAnF2/ssKwrrszP9t5q050= cosmossdk.io/depinject v1.0.0/go.mod h1:zxK/h3HgHoA/eJVtiSsoaRaRA2D5U4cJ5thIG4ssbB8= cosmossdk.io/errors v1.0.1 h1:bzu+Kcr0kS/1DuPBtUFdWjzLqyUuCiyHjyJB6srBV/0= @@ -14,8 +16,8 @@ cosmossdk.io/log v1.4.1 h1:wKdjfDRbDyZRuWa8M+9nuvpVYxrEOwbD/CA8hvhU8QM= cosmossdk.io/log v1.4.1/go.mod h1:k08v0Pyq+gCP6phvdI6RCGhLf/r425UT6Rk/m+o74rU= cosmossdk.io/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE= cosmossdk.io/math v1.3.0/go.mod h1:vnRTxewy+M7BtXBNFybkuhSH4WfedVAAnERHgVFhp3k= -cosmossdk.io/schema v0.2.0 h1:UH5CR1DqUq8yP+5Np8PbvG4YX0zAUsTN2Qk6yThmfMk= -cosmossdk.io/schema v0.2.0/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= +cosmossdk.io/schema v0.3.1-0.20240930054013-7c6e0388a3f9 h1:DmOoS/1PeY6Ih0hAVlJ69kLMUrLV+TCbfICrZtB1vdU= +cosmossdk.io/schema v0.3.1-0.20240930054013-7c6e0388a3f9/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMbk2FiG/kXiLl8BRyzTWDw7gX/Hz7Dd5eDMs= @@ -290,8 +292,8 @@ github.com/hdevalence/ed25519consensus v0.2.0/go.mod h1:w3BHWjwJbFU29IRHL1Iqkw3s github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/huandu/go-assert v1.1.5 h1:fjemmA7sSfYHJD7CUqs9qTwwfdNAx7/j2/ZlHXzNB3c= github.com/huandu/go-assert v1.1.5/go.mod h1:yOLvuqZwmcHIC5rIzrBhT7D3Q9c3GFnd0JrPVhn/06U= -github.com/huandu/skiplist v1.2.0 h1:gox56QD77HzSC0w+Ws3MH3iie755GBJU1OER3h5VsYw= -github.com/huandu/skiplist v1.2.0/go.mod h1:7v3iFjLcSAzO4fN5B8dvebvo/qsfumiLiDXMrPiHF9w= +github.com/huandu/skiplist v1.2.1 h1:dTi93MgjwErA/8idWTzIw4Y1kZsMWx35fmI2c8Rij7w= +github.com/huandu/skiplist v1.2.1/go.mod h1:7v3iFjLcSAzO4fN5B8dvebvo/qsfumiLiDXMrPiHF9w= github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI= github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= @@ -400,8 +402,8 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= -github.com/prometheus/client_golang v1.20.3 h1:oPksm4K8B+Vt35tUhw6GbSNSgVlVSBH0qELP/7u83l4= -github.com/prometheus/client_golang v1.20.3/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_golang v1.20.4 h1:Tgh3Yr67PaOv/uTqloMsCEdeuFTatm5zIq5+qNN23vI= +github.com/prometheus/client_golang v1.20.4/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -410,8 +412,8 @@ github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= -github.com/prometheus/common v0.59.1 h1:LXb1quJHWm1P6wq/U824uxYi4Sg0oGvNeUm1z5dJoX0= -github.com/prometheus/common v0.59.1/go.mod h1:GpWM7dewqmVYcd7SmRaiWVe9SSqjf0UrwnYnpEZNuT0= +github.com/prometheus/common v0.60.0 h1:+V9PAREWNvJMAuJ1x1BaWl9dewMW4YrHZQbx0sJNllA= +github.com/prometheus/common v0.60.0/go.mod h1:h0LYf1R1deLSKtD4Vdg8gy4RuOvENW2J/h19V5NADQw= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/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= @@ -630,10 +632,10 @@ google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEY google.golang.org/genproto v0.0.0-20220314164441-57ef72a4c106/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E= google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de h1:F6qOa9AZTYJXOUEr4jDysRDLrm4PHePlge4v4TGAlxY= google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:VUhTRKeHn9wwcdrk73nvdC9gF178Tzhmt/qyaFcPLSo= -google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 h1:+rdxYoE3E5htTEWIe15GlN6IfvbURM//Jt0mmkmm6ZU= -google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117/go.mod h1:OimBR/bc1wPO9iV4NC2bpyjy3VnAwZh5EBPQdtaE5oo= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:pPJltXNxVzT4pK9yD8vR9X75DaWYYmLGMsEvBfFQZzQ= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= +google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 h1:wKguEg1hsxI2/L3hUYrpo1RVi48K+uTyzKqprwLXsb8= +google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142/go.mod h1:d6be+8HhtEtucleCbxpPW9PA9XwISACu8nvpPqF0BVo= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f h1:cUMEy+8oS78BWIH9OWazBkzbr090Od9tWBNtZHkOhf0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= @@ -644,8 +646,8 @@ google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= -google.golang.org/grpc v1.66.2 h1:3QdXkuq3Bkh7w+ywLdLvM56cmGvQHUMZpiCzt6Rqaoo= -google.golang.org/grpc v1.66.2/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y= +google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E= +google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= 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= diff --git a/x/accounts/depinject.go b/x/accounts/depinject.go index 1110a0525a20..4bdcfdc6479c 100644 --- a/x/accounts/depinject.go +++ b/x/accounts/depinject.go @@ -1,19 +1,12 @@ package accounts import ( - "context" - modulev1 "cosmossdk.io/api/cosmos/accounts/module/v1" - signingv1beta1 "cosmossdk.io/api/cosmos/tx/signing/v1beta1" "cosmossdk.io/core/address" "cosmossdk.io/core/appmodule" "cosmossdk.io/depinject" "cosmossdk.io/depinject/appconfig" "cosmossdk.io/x/accounts/accountstd" - baseaccount "cosmossdk.io/x/accounts/defaults/base" - "cosmossdk.io/x/accounts/defaults/lockup" - "cosmossdk.io/x/accounts/defaults/multisig" - "cosmossdk.io/x/tx/signing" "github.com/cosmos/cosmos-sdk/codec" cdctypes "github.com/cosmos/cosmos-sdk/codec/types" @@ -39,8 +32,7 @@ type ModuleInputs struct { AddressCodec address.Codec Registry cdctypes.InterfaceRegistry - // TODO: Add a way to inject custom accounts. - // Currently only the base account is supported. + Accounts []accountstd.DepinjectAccount // at least one account must be provided } type ModuleOutputs struct { @@ -50,32 +42,19 @@ type ModuleOutputs struct { Module appmodule.AppModule } -var _ signing.SignModeHandler = directHandler{} - -type directHandler struct{} - -func (s directHandler) Mode() signingv1beta1.SignMode { - return signingv1beta1.SignMode_SIGN_MODE_DIRECT -} - -func (s directHandler) GetSignBytes(_ context.Context, _ signing.SignerData, _ signing.TxData) ([]byte, error) { - panic("not implemented") -} - func ProvideModule(in ModuleInputs) ModuleOutputs { - handler := directHandler{} - account := baseaccount.NewAccount("base", signing.NewHandlerMap(handler), baseaccount.WithSecp256K1PubKey()) - accountskeeper, err := NewKeeper( - in.Cdc, in.Environment, in.AddressCodec, in.Registry, account, - accountstd.AddAccount(lockup.CONTINUOUS_LOCKING_ACCOUNT, lockup.NewContinuousLockingAccount), - accountstd.AddAccount(lockup.PERIODIC_LOCKING_ACCOUNT, lockup.NewPeriodicLockingAccount), - accountstd.AddAccount(lockup.DELAYED_LOCKING_ACCOUNT, lockup.NewDelayedLockingAccount), - accountstd.AddAccount(lockup.PERMANENT_LOCKING_ACCOUNT, lockup.NewPermanentLockingAccount), - accountstd.AddAccount(multisig.MULTISIG_ACCOUNT, multisig.NewAccount), + accCreators := make([]accountstd.AccountCreatorFunc, len(in.Accounts)) + for i, acc := range in.Accounts { + accCreators[i] = acc.MakeAccount + } + + accountsKeeper, err := NewKeeper( + in.Cdc, in.Environment, in.AddressCodec, in.Registry, + accCreators..., ) if err != nil { panic(err) } - m := NewAppModule(in.Cdc, accountskeeper) - return ModuleOutputs{AccountsKeeper: accountskeeper, Module: m} + m := NewAppModule(in.Cdc, accountsKeeper) + return ModuleOutputs{AccountsKeeper: accountsKeeper, Module: m} } diff --git a/x/accounts/go.mod b/x/accounts/go.mod index 338cb3cc8a18..3232de28c027 100644 --- a/x/accounts/go.mod +++ b/x/accounts/go.mod @@ -3,25 +3,25 @@ module cosmossdk.io/x/accounts go 1.23.1 require ( - cosmossdk.io/api v0.7.5 + cosmossdk.io/api v0.7.6 cosmossdk.io/collections v0.4.0 - cosmossdk.io/core v1.0.0-alpha.2 - cosmossdk.io/core/testing v0.0.0-00010101000000-000000000000 + cosmossdk.io/core v1.0.0-alpha.4 + cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29 cosmossdk.io/depinject v1.0.0 - cosmossdk.io/x/accounts/defaults/multisig v0.0.0-00010101000000-000000000000 cosmossdk.io/x/bank v0.0.0-20240226161501-23359a0b6d91 cosmossdk.io/x/tx v0.13.3 github.com/cosmos/cosmos-sdk v0.53.0 github.com/cosmos/gogoproto v1.7.0 - github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 github.com/spf13/cobra v1.8.1 github.com/stretchr/testify v1.9.0 - google.golang.org/grpc v1.66.2 + google.golang.org/grpc v1.67.1 google.golang.org/protobuf v1.34.2 ) require ( github.com/cockroachdb/fifo v0.0.0-20240606204812-0bbfbd93a7ce // indirect + github.com/cosmos/cosmos-db v1.0.3-0.20240911104526-ddc3f09bfc22 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect github.com/google/uuid v1.6.0 // indirect ) @@ -31,10 +31,8 @@ require ( cosmossdk.io/errors v1.0.1 // indirect cosmossdk.io/log v1.4.1 // indirect cosmossdk.io/math v1.3.0 - cosmossdk.io/schema v0.2.0 // indirect + cosmossdk.io/schema v0.3.1-0.20240930054013-7c6e0388a3f9 // indirect cosmossdk.io/store v1.1.1-0.20240418092142-896cdf1971bc // indirect - cosmossdk.io/x/accounts/defaults/lockup v0.0.0-20240417181816-5e7aae0db1f5 - cosmossdk.io/x/distribution v0.0.0-00010101000000-000000000000 // indirect cosmossdk.io/x/staking v0.0.0-00010101000000-000000000000 // indirect filippo.io/edwards25519 v1.1.0 // indirect github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect @@ -55,7 +53,6 @@ require ( github.com/cometbft/cometbft-db v0.15.0 // indirect github.com/cometbft/cometbft/api v1.0.0-rc.1 // indirect github.com/cosmos/btcutil v1.0.5 // indirect - github.com/cosmos/cosmos-db v1.0.3-0.20240911104526-ddc3f09bfc22 // indirect github.com/cosmos/cosmos-proto v1.0.0-beta.5 // indirect github.com/cosmos/crypto v0.1.2 // indirect github.com/cosmos/go-bip39 v1.0.0 // indirect @@ -103,7 +100,7 @@ require ( github.com/hashicorp/hcl v1.0.0 // indirect github.com/hashicorp/yamux v0.1.1 // indirect github.com/hdevalence/ed25519consensus v0.2.0 // indirect - github.com/huandu/skiplist v1.2.0 // indirect + github.com/huandu/skiplist v1.2.1 // indirect github.com/iancoleman/strcase v0.3.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jmhodges/levigo v1.0.0 // indirect @@ -126,9 +123,9 @@ require ( github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/client_golang v1.20.3 // indirect + github.com/prometheus/client_golang v1.20.4 // indirect github.com/prometheus/client_model v0.6.1 // indirect - github.com/prometheus/common v0.59.1 // indirect + github.com/prometheus/common v0.60.0 // indirect github.com/prometheus/procfs v0.15.1 // indirect github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect github.com/rogpeppe/go-internal v1.12.0 // indirect @@ -164,8 +161,8 @@ require ( golang.org/x/text v0.18.0 // indirect golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect gotest.tools/v3 v3.5.1 // indirect @@ -179,14 +176,8 @@ replace github.com/cosmos/cosmos-sdk => ../../. replace ( cosmossdk.io/api => ../../api cosmossdk.io/collections => ../../collections - cosmossdk.io/core/testing => ../../core/testing cosmossdk.io/store => ../../store - cosmossdk.io/x/accounts/defaults/lockup => ./defaults/lockup - cosmossdk.io/x/accounts/defaults/multisig => ./defaults/multisig cosmossdk.io/x/bank => ../bank - cosmossdk.io/x/distribution => ../distribution - cosmossdk.io/x/mint => ../mint - cosmossdk.io/x/slashing => ../slashing cosmossdk.io/x/staking => ../staking cosmossdk.io/x/tx => ../tx ) diff --git a/x/accounts/go.sum b/x/accounts/go.sum index cd6b45de5cf6..7588b565a0d7 100644 --- a/x/accounts/go.sum +++ b/x/accounts/go.sum @@ -4,8 +4,10 @@ buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.34.2-20240130113600-88e buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.34.2-20240130113600-88ef6483f90f.2/go.mod h1:HqcXMSa5qnNuakaMUo+hWhF51mKbcrZxGl9Vp5EeJXc= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cosmossdk.io/core v1.0.0-alpha.2 h1:epU0Xwces4Rgl5bMhHHkXGaGDcyucNGlC/JDH+Suckg= -cosmossdk.io/core v1.0.0-alpha.2/go.mod h1:abgLjeFLhtuKIYZWSPlVUgQBrKObO7ULV35KYfexE90= +cosmossdk.io/core v1.0.0-alpha.4 h1:9iuroT9ejDYETCsGkzkvs/wAY/5UFl7nCIINFRxyMJY= +cosmossdk.io/core v1.0.0-alpha.4/go.mod h1:3u9cWq1FAVtiiCrDPpo4LhR+9V6k/ycSG4/Y/tREWCY= +cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29 h1:NxxUo0GMJUbIuVg0R70e3cbn9eFTEuMr7ev1AFvypdY= +cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29/go.mod h1:8s2tPeJtSiQuoyPmr2Ag7meikonISO4Fv4MoO8+ORrs= cosmossdk.io/depinject v1.0.0 h1:dQaTu6+O6askNXO06+jyeUAnF2/ssKwrrszP9t5q050= cosmossdk.io/depinject v1.0.0/go.mod h1:zxK/h3HgHoA/eJVtiSsoaRaRA2D5U4cJ5thIG4ssbB8= cosmossdk.io/errors v1.0.1 h1:bzu+Kcr0kS/1DuPBtUFdWjzLqyUuCiyHjyJB6srBV/0= @@ -14,8 +16,8 @@ cosmossdk.io/log v1.4.1 h1:wKdjfDRbDyZRuWa8M+9nuvpVYxrEOwbD/CA8hvhU8QM= cosmossdk.io/log v1.4.1/go.mod h1:k08v0Pyq+gCP6phvdI6RCGhLf/r425UT6Rk/m+o74rU= cosmossdk.io/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE= cosmossdk.io/math v1.3.0/go.mod h1:vnRTxewy+M7BtXBNFybkuhSH4WfedVAAnERHgVFhp3k= -cosmossdk.io/schema v0.2.0 h1:UH5CR1DqUq8yP+5Np8PbvG4YX0zAUsTN2Qk6yThmfMk= -cosmossdk.io/schema v0.2.0/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= +cosmossdk.io/schema v0.3.1-0.20240930054013-7c6e0388a3f9 h1:DmOoS/1PeY6Ih0hAVlJ69kLMUrLV+TCbfICrZtB1vdU= +cosmossdk.io/schema v0.3.1-0.20240930054013-7c6e0388a3f9/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMbk2FiG/kXiLl8BRyzTWDw7gX/Hz7Dd5eDMs= @@ -290,8 +292,8 @@ github.com/hdevalence/ed25519consensus v0.2.0/go.mod h1:w3BHWjwJbFU29IRHL1Iqkw3s github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/huandu/go-assert v1.1.5 h1:fjemmA7sSfYHJD7CUqs9qTwwfdNAx7/j2/ZlHXzNB3c= github.com/huandu/go-assert v1.1.5/go.mod h1:yOLvuqZwmcHIC5rIzrBhT7D3Q9c3GFnd0JrPVhn/06U= -github.com/huandu/skiplist v1.2.0 h1:gox56QD77HzSC0w+Ws3MH3iie755GBJU1OER3h5VsYw= -github.com/huandu/skiplist v1.2.0/go.mod h1:7v3iFjLcSAzO4fN5B8dvebvo/qsfumiLiDXMrPiHF9w= +github.com/huandu/skiplist v1.2.1 h1:dTi93MgjwErA/8idWTzIw4Y1kZsMWx35fmI2c8Rij7w= +github.com/huandu/skiplist v1.2.1/go.mod h1:7v3iFjLcSAzO4fN5B8dvebvo/qsfumiLiDXMrPiHF9w= github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI= github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= @@ -400,8 +402,8 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= -github.com/prometheus/client_golang v1.20.3 h1:oPksm4K8B+Vt35tUhw6GbSNSgVlVSBH0qELP/7u83l4= -github.com/prometheus/client_golang v1.20.3/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_golang v1.20.4 h1:Tgh3Yr67PaOv/uTqloMsCEdeuFTatm5zIq5+qNN23vI= +github.com/prometheus/client_golang v1.20.4/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -410,8 +412,8 @@ github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= -github.com/prometheus/common v0.59.1 h1:LXb1quJHWm1P6wq/U824uxYi4Sg0oGvNeUm1z5dJoX0= -github.com/prometheus/common v0.59.1/go.mod h1:GpWM7dewqmVYcd7SmRaiWVe9SSqjf0UrwnYnpEZNuT0= +github.com/prometheus/common v0.60.0 h1:+V9PAREWNvJMAuJ1x1BaWl9dewMW4YrHZQbx0sJNllA= +github.com/prometheus/common v0.60.0/go.mod h1:h0LYf1R1deLSKtD4Vdg8gy4RuOvENW2J/h19V5NADQw= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/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= @@ -634,10 +636,10 @@ google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEY google.golang.org/genproto v0.0.0-20220314164441-57ef72a4c106/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E= google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de h1:F6qOa9AZTYJXOUEr4jDysRDLrm4PHePlge4v4TGAlxY= google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:VUhTRKeHn9wwcdrk73nvdC9gF178Tzhmt/qyaFcPLSo= -google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 h1:+rdxYoE3E5htTEWIe15GlN6IfvbURM//Jt0mmkmm6ZU= -google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117/go.mod h1:OimBR/bc1wPO9iV4NC2bpyjy3VnAwZh5EBPQdtaE5oo= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:pPJltXNxVzT4pK9yD8vR9X75DaWYYmLGMsEvBfFQZzQ= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= +google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 h1:wKguEg1hsxI2/L3hUYrpo1RVi48K+uTyzKqprwLXsb8= +google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142/go.mod h1:d6be+8HhtEtucleCbxpPW9PA9XwISACu8nvpPqF0BVo= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f h1:cUMEy+8oS78BWIH9OWazBkzbr090Od9tWBNtZHkOhf0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= @@ -648,8 +650,8 @@ google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= -google.golang.org/grpc v1.66.2 h1:3QdXkuq3Bkh7w+ywLdLvM56cmGvQHUMZpiCzt6Rqaoo= -google.golang.org/grpc v1.66.2/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y= +google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E= +google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= 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= diff --git a/x/accounts/proto/cosmos/accounts/defaults/base/v1/base.proto b/x/accounts/proto/cosmos/accounts/defaults/base/v1/base.proto index 1df7f92b501d..3661c52c6108 100644 --- a/x/accounts/proto/cosmos/accounts/defaults/base/v1/base.proto +++ b/x/accounts/proto/cosmos/accounts/defaults/base/v1/base.proto @@ -10,6 +10,9 @@ import "google/protobuf/any.proto"; message MsgInit { // pub_key defines a pubkey for the account arbitrary encapsulated. google.protobuf.Any pub_key = 1; + // init_sequence defines the initial sequence of the account. + // Defaults to zero if not set. + uint64 init_sequence = 2; } // MsgInitResponse is the response returned after base account initialization. diff --git a/x/auth/CHANGELOG.md b/x/auth/CHANGELOG.md index 6155638ff2e9..d0b1ca0509bb 100644 --- a/x/auth/CHANGELOG.md +++ b/x/auth/CHANGELOG.md @@ -60,7 +60,8 @@ Ref: https://keepachangelog.com/en/1.0.0/ * [#18817](https://github.com/cosmos/cosmos-sdk/pull/18817) SigVerification, GasConsumption, IncreaseSequence ante decorators have all been joined into one SigVerification decorator. Gas consumption during TX validation flow has reduced. * [#19093](https://github.com/cosmos/cosmos-sdk/pull/19093) SetPubKeyDecorator was merged into SigVerification, gas consumption is almost halved for a simple tx. * [#19535](https://github.com/cosmos/cosmos-sdk/pull/19535) Remove vesting account creation when the chain is running. The accounts module is required for creating [#vesting accounts](../accounts/defaults/lockup/README.md) on a running chain. - +* [#21688](https://github.com/cosmos/cosmos-sdk/pull/21688) Allow x/accounts to be queriable from the `AccountInfo` and `Account` gRPC endpoints +* [#21820](https://github.com/cosmos/cosmos-sdk/pull/21820) Allow x/auth `BaseAccount` to migrate to a `x/accounts` via the new `MsgMigrateAccount`. ### Bug Fixes * [#19148](https://github.com/cosmos/cosmos-sdk/pull/19148) Checks the consumed gas for verifying a multisig pubKey signature during simulation. diff --git a/x/auth/ante/basic_test.go b/x/auth/ante/basic_test.go index 389096d3d7c6..1a5687b92f62 100644 --- a/x/auth/ante/basic_test.go +++ b/x/auth/ante/basic_test.go @@ -99,7 +99,7 @@ func TestValidateMemo(t *testing.T) { } func TestConsumeGasForTxSize(t *testing.T) { - t.Skip() // TODO(@julienrbrt) Fix after https://github.com/cosmos/cosmos-sdk/pull/20072 + t.Skip() // TO FIX BEFORE 0.52 FINAL. suite := SetupTestSuite(t, true) @@ -221,8 +221,6 @@ func TestTxHeightTimeoutDecorator(t *testing.T) { } for _, tc := range testCases { - tc := tc - t.Run(tc.name, func(t *testing.T) { suite.txBuilder = suite.clientCtx.TxConfig.NewTxBuilder() diff --git a/x/auth/ante/unorderedtx/snapshotter_test.go b/x/auth/ante/unorderedtx/snapshotter_test.go index fc5ce003d896..e5a5e2c528fb 100644 --- a/x/auth/ante/unorderedtx/snapshotter_test.go +++ b/x/auth/ante/unorderedtx/snapshotter_test.go @@ -49,10 +49,9 @@ func TestSnapshotter(t *testing.T) { // start the manager and wait a bit for the background purge loop to run txm2.Start() - time.Sleep(time.Millisecond * 5) - txm2.OnNewBlock(currentTime.Add(time.Second * 200)) - time.Sleep(time.Second * 5) // the loop runs every 5 seconds, so we need to wait for that - require.Equal(t, 0, txm2.Size()) + txm2.OnNewBlock(currentTime.Add(time.Second * 200)) // blocks until channel is read in purge loop + // the loop runs every 5 seconds, so we need to wait for that + require.Eventually(t, func() bool { return txm2.Size() == 0 }, 6*time.Second, 500*time.Millisecond) // restore with timestamp < timeout time which should result in all unordered txs synced txm3 := unorderedtx.NewManager(dataDir) diff --git a/x/auth/autocli.go b/x/auth/autocli.go index 676a3e4af702..0dabf876a56f 100644 --- a/x/auth/autocli.go +++ b/x/auth/autocli.go @@ -38,7 +38,7 @@ func (am AppModule) AutoCLIOptions() *autocliv1.ModuleOptions { RpcMethod: "AccountAddressByID", Use: "address-by-acc-num ", Short: "Query account address by account number", - PositionalArgs: []*autocliv1.PositionalArgDescriptor{{ProtoField: "id"}}, + PositionalArgs: []*autocliv1.PositionalArgDescriptor{{ProtoField: "account_id"}}, }, { RpcMethod: "ModuleAccounts", diff --git a/x/auth/client/tx_test.go b/x/auth/client/tx_test.go index 18ee2cd5a4d2..4c35286d7427 100644 --- a/x/auth/client/tx_test.go +++ b/x/auth/client/tx_test.go @@ -172,7 +172,6 @@ func TestBatchScanner_Scan(t *testing.T) { } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { scanner, i := authclient.NewBatchScanner(clientCtx.TxConfig, strings.NewReader(tt.batch)), 0 for scanner.Scan() { diff --git a/x/auth/keeper/grpc_query.go b/x/auth/keeper/grpc_query.go index 402eb6b0a149..101c0755801a 100644 --- a/x/auth/keeper/grpc_query.go +++ b/x/auth/keeper/grpc_query.go @@ -80,7 +80,11 @@ func (s queryServer) Account(ctx context.Context, req *types.QueryAccountRequest } account := s.k.GetAccount(ctx, addr) if account == nil { - return nil, status.Errorf(codes.NotFound, "account %s not found", req.Address) + xAccount, err := s.getFromXAccounts(ctx, addr) + if err != nil { + return nil, status.Errorf(codes.NotFound, "account %s not found", req.Address) + } + return &types.QueryAccountResponse{Account: xAccount.Account}, nil } any, err := codectypes.NewAnyWithValue(account) @@ -224,7 +228,13 @@ func (s queryServer) AccountInfo(ctx context.Context, req *types.QueryAccountInf account := s.k.GetAccount(ctx, addr) if account == nil { - return nil, status.Errorf(codes.NotFound, "account %s not found", req.Address) + xAccount, err := s.getFromXAccounts(ctx, addr) + // account info is nil it means that the account can be encapsulated into a + // legacy account representation but not a base account one. + if err != nil || xAccount.Base == nil { + return nil, status.Errorf(codes.NotFound, "account %s not found", req.Address) + } + return &types.QueryAccountInfoResponse{Info: xAccount.Base}, nil } // if there is no public key, avoid serializing the nil value @@ -246,3 +256,26 @@ func (s queryServer) AccountInfo(ctx context.Context, req *types.QueryAccountInf }, }, nil } + +var ( + errNotXAccount = errors.New("not an x/account") + errInvalidLegacyAccountImpl = errors.New("invalid legacy account implementation") +) + +func (s queryServer) getFromXAccounts(ctx context.Context, address []byte) (*types.QueryLegacyAccountResponse, error) { + if !s.k.AccountsModKeeper.IsAccountsModuleAccount(ctx, address) { + return nil, errNotXAccount + } + + // attempt to check if it can be queried for a legacy account representation. + resp, err := s.k.AccountsModKeeper.Query(ctx, address, &types.QueryLegacyAccount{}) + if err != nil { + return nil, err + } + + typedResp, ok := resp.(*types.QueryLegacyAccountResponse) + if !ok { + return nil, errInvalidLegacyAccountImpl + } + return typedResp, nil +} diff --git a/x/auth/keeper/grpc_query_test.go b/x/auth/keeper/grpc_query_test.go index 82e9cfe573fc..6f5a8700779e 100644 --- a/x/auth/keeper/grpc_query_test.go +++ b/x/auth/keeper/grpc_query_test.go @@ -8,6 +8,7 @@ import ( "sort" "github.com/cosmos/gogoproto/proto" + "github.com/golang/mock/gomock" "github.com/cosmos/cosmos-sdk/testutil/testdata" sdk "github.com/cosmos/cosmos-sdk/types" @@ -135,6 +136,7 @@ func (suite *KeeperTestSuite) TestGRPCQueryAccount() { for _, tc := range testCases { suite.Run(fmt.Sprintf("Case %s", tc.msg), func() { suite.SetupTest() // reset + suite.acctsModKeeper.EXPECT().IsAccountsModuleAccount(gomock.Any(), gomock.Any()).Return(false).AnyTimes() tc.malleate() res, err := suite.queryClient.Account(suite.ctx, req) diff --git a/x/auth/keeper/msg_server.go b/x/auth/keeper/msg_server.go index 84155981bb0b..649e2d4e5efe 100644 --- a/x/auth/keeper/msg_server.go +++ b/x/auth/keeper/msg_server.go @@ -4,7 +4,14 @@ import ( "context" "errors" "fmt" + "reflect" + "strings" + gogoproto "github.com/cosmos/gogoproto/proto" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + + codectypes "github.com/cosmos/cosmos-sdk/codec/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/cosmos/cosmos-sdk/x/auth/types" ) @@ -68,3 +75,61 @@ func (ms msgServer) UpdateParams(ctx context.Context, msg *types.MsgUpdateParams return &types.MsgUpdateParamsResponse{}, nil } + +func (ms msgServer) MigrateAccount(ctx context.Context, msg *types.MsgMigrateAccount) (*types.MsgMigrateAccountResponse, error) { + signer, err := ms.ak.AddressCodec().StringToBytes(msg.Signer) + if err != nil { + return nil, sdkerrors.ErrInvalidAddress.Wrapf("invalid signer address: %s", err) + } + + acc := ms.ak.GetAccount(ctx, signer) + if acc == nil { + return nil, sdkerrors.ErrUnknownAddress.Wrapf("account %s does not exist", signer) + } + + // check if account type is valid or not + _, isBaseAccount := (acc).(*types.BaseAccount) + if !isBaseAccount { + return nil, status.Error(codes.InvalidArgument, "only BaseAccount can be migrated") + } + + // unwrap any msg + initMsg, err := unpackAnyRaw(msg.AccountInitMsg) + if err != nil { + return nil, err + } + + initResp, err := ms.ak.AccountsModKeeper.MigrateLegacyAccount(ctx, signer, acc.GetAccountNumber(), msg.AccountType, initMsg) + if err != nil { + return nil, err + } + + // account is then removed from state + ms.ak.RemoveAccount(ctx, acc) + + initRespAny, err := codectypes.NewAnyWithValue(initResp) + if err != nil { + return nil, err + } + + return &types.MsgMigrateAccountResponse{InitResponse: initRespAny}, nil +} + +func unpackAnyRaw(m *codectypes.Any) (gogoproto.Message, error) { + if m == nil { + return nil, fmt.Errorf("cannot unpack nil any") + } + split := strings.Split(m.TypeUrl, "/") + name := split[len(split)-1] + typ := gogoproto.MessageType(name) + if typ == nil { + return nil, fmt.Errorf("no message type found for %s", name) + } + concreteMsg := reflect.New(typ.Elem()).Interface().(gogoproto.Message) + err := gogoproto.Unmarshal(m.Value, concreteMsg) + if err != nil { + return nil, err + } + + return concreteMsg, nil +} diff --git a/x/auth/keeper/msg_server_test.go b/x/auth/keeper/msg_server_test.go index f65334ea5f1c..3e7a65cce451 100644 --- a/x/auth/keeper/msg_server_test.go +++ b/x/auth/keeper/msg_server_test.go @@ -120,7 +120,6 @@ func (s *KeeperTestSuite) TestUpdateParams() { } for _, tc := range testCases { - tc := tc s.Run(tc.name, func() { _, err := s.msgServer.UpdateParams(s.ctx, tc.req) if tc.expectErr { @@ -190,7 +189,6 @@ func (s *KeeperTestSuite) TestNonAtomicExec() { }).AnyTimes() for _, tc := range testCases { - tc := tc s.Run(tc.name, func() { _, err := s.msgServer.NonAtomicExec(s.ctx, tc.req) if tc.expectErr { diff --git a/x/auth/migrations/legacytx/stdtx_test.go b/x/auth/migrations/legacytx/stdtx_test.go index cdb28e978b2b..27156448d9ba 100644 --- a/x/auth/migrations/legacytx/stdtx_test.go +++ b/x/auth/migrations/legacytx/stdtx_test.go @@ -44,7 +44,7 @@ func TestStdSignBytes(t *testing.T) { Amount: []*basev1beta1.Coin{{Denom: "atom", Amount: "150"}}, GasLimit: 100000, } - msgStr := fmt.Sprintf(`{"type":"testpb/TestMsg","value":{"decField":"0","signers":["%s"]}}`, addr) + msgStr := fmt.Sprintf(`{"type":"testpb/TestMsg","value":{"decField":"0.000000000000000000","signers":["%s"]}}`, addr) tests := []struct { name string args args @@ -90,7 +90,6 @@ func TestStdSignBytes(t *testing.T) { FileResolver: proto.HybridResolver, }) for i, tc := range tests { - tc := tc t.Run(tc.name, func(t *testing.T) { anyMsgs := make([]*anypb.Any, len(tc.args.msgs)) for j, msg := range tc.args.msgs { diff --git a/x/auth/module.go b/x/auth/module.go index 095304de78eb..b959fcde5408 100644 --- a/x/auth/module.go +++ b/x/auth/module.go @@ -15,6 +15,7 @@ import ( "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/simsx" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/module" simtypes "github.com/cosmos/cosmos-sdk/types/simulation" @@ -188,17 +189,12 @@ func (am AppModule) GenerateGenesisState(simState *module.SimulationState) { simulation.RandomizedGenState(simState, am.randGenAccountsFn) } -// ProposalMsgs returns msgs used for governance proposals for simulations. -func (AppModule) ProposalMsgs(simState module.SimulationState) []simtypes.WeightedProposalMsg { - return simulation.ProposalMsgs() +// ProposalMsgsX returns msgs used for governance proposals for simulations. +func (AppModule) ProposalMsgsX(weights simsx.WeightSource, reg simsx.Registry) { + reg.Add(weights.Get("msg_update_params", 100), simulation.MsgUpdateParamsFactory()) } // RegisterStoreDecoder registers a decoder for auth module's types func (am AppModule) RegisterStoreDecoder(sdr simtypes.StoreDecoderRegistry) { sdr[types.StoreKey] = simtypes.NewStoreDecoderFuncFromCollectionsSchema(am.accountKeeper.Schema) } - -// WeightedOperations doesn't return any auth module operation. -func (AppModule) WeightedOperations(_ module.SimulationState) []simtypes.WeightedOperation { - return nil -} diff --git a/x/auth/proto/buf.gen.gogo.yaml b/x/auth/proto/buf.gen.gogo.yaml deleted file mode 100644 index db36231d0c82..000000000000 --- a/x/auth/proto/buf.gen.gogo.yaml +++ /dev/null @@ -1,8 +0,0 @@ -version: v1 -plugins: - - name: gocosmos - out: .. - opt: plugins=grpc,Mgoogle/protobuf/any.proto=github.com/cosmos/gogoproto/types/any - - name: grpc-gateway - out: .. - opt: logtostderr=true,allow_colon_final_segments=true diff --git a/x/auth/proto/buf.gen.pulsar.yaml b/x/auth/proto/buf.gen.pulsar.yaml deleted file mode 100644 index 88a5b0419d7f..000000000000 --- a/x/auth/proto/buf.gen.pulsar.yaml +++ /dev/null @@ -1,18 +0,0 @@ -version: v1 -managed: - enabled: true - go_package_prefix: - default: cosmossdk.io/api - except: - - buf.build/googleapis/googleapis - - buf.build/cosmos/gogo-proto - - buf.build/cosmos/cosmos-proto - override: - buf.build/cosmos/cosmos-sdk: cosmossdk.io/api -plugins: - - name: go-pulsar - out: .. - opt: paths=source_relative - - name: go-grpc - out: .. - opt: paths=source_relative diff --git a/x/auth/proto/buf.lock b/x/auth/proto/buf.lock deleted file mode 100644 index 28c135cc08bb..000000000000 --- a/x/auth/proto/buf.lock +++ /dev/null @@ -1,28 +0,0 @@ -# Generated by buf. DO NOT EDIT. -version: v1 -deps: - - remote: buf.build - owner: cosmos - repository: cosmos-proto - commit: 04467658e59e44bbb22fe568206e1f70 - digest: shake256:73a640bd60e0c523b0f8237ff34eab67c45a38b64bbbde1d80224819d272dbf316ac183526bd245f994af6608b025f5130483d0133c5edd385531326b5990466 - - remote: buf.build - owner: cosmos - repository: cosmos-sdk - commit: cf13c7d232dd405180c2af616fa8a075 - digest: shake256:769a38e306a98339b549bc96991c97fae8bd3ceb1a7646c7bfe9a74e406ab068372970fbc5abda1891e2f3c36527cf2d3a25f631739d36900787226e564bb612 - - remote: buf.build - owner: cosmos - repository: gogo-proto - commit: 5e5b9fdd01804356895f8f79a6f1ddc1 - digest: shake256:0b85da49e2e5f9ebc4806eae058e2f56096ff3b1c59d1fb7c190413dd15f45dd456f0b69ced9059341c80795d2b6c943de15b120a9e0308b499e43e4b5fc2952 - - remote: buf.build - owner: googleapis - repository: googleapis - commit: 28151c0d0a1641bf938a7672c500e01d - digest: shake256:49215edf8ef57f7863004539deff8834cfb2195113f0b890dd1f67815d9353e28e668019165b9d872395871eeafcbab3ccfdb2b5f11734d3cca95be9e8d139de - - remote: buf.build - owner: protocolbuffers - repository: wellknowntypes - commit: 657250e6a39648cbb169d079a60bd9ba - digest: shake256:00de25001b8dd2e29d85fc4bcc3ede7aed886d76d67f5e0f7a9b320b90f871d3eb73507d50818d823a0512f3f8db77a11c043685528403e31ff3fef18323a9fb diff --git a/x/auth/proto/buf.yaml b/x/auth/proto/buf.yaml deleted file mode 100644 index e59a92092e2b..000000000000 --- a/x/auth/proto/buf.yaml +++ /dev/null @@ -1,18 +0,0 @@ -version: v1 -name: buf.build/mods/auth -deps: - - buf.build/cosmos/cosmos-sdk # pin the Cosmos SDK version - - buf.build/cosmos/cosmos-proto - - buf.build/cosmos/gogo-proto - - buf.build/googleapis/googleapis -lint: - use: - - DEFAULT - - COMMENTS - - FILE_LOWER_SNAKE_CASE - except: - - UNARY_RPC - - COMMENT_FIELD - - SERVICE_SUFFIX - - PACKAGE_VERSION_SUFFIX - - RPC_REQUEST_STANDARD_NAME diff --git a/x/auth/simulation/genesis.go b/x/auth/simulation/genesis.go index c6984cc355e8..7c18882fd325 100644 --- a/x/auth/simulation/genesis.go +++ b/x/auth/simulation/genesis.go @@ -1,8 +1,6 @@ package simulation import ( - "encoding/json" - "fmt" "math/rand" sdk "github.com/cosmos/cosmos-sdk/types" @@ -113,10 +111,5 @@ func RandomizedGenState(simState *module.SimulationState, randGenAccountsFn type authGenesis := types.NewGenesisState(params, genesisAccs) - bz, err := json.MarshalIndent(&authGenesis.Params, "", " ") - if err != nil { - panic(err) - } - fmt.Printf("Selected randomly generated auth parameters:\n%s\n", bz) simState.GenState[types.ModuleName] = simState.Cdc.MustMarshalJSON(authGenesis) } diff --git a/x/auth/simulation/msg_factory.go b/x/auth/simulation/msg_factory.go new file mode 100644 index 000000000000..83bcca3029d4 --- /dev/null +++ b/x/auth/simulation/msg_factory.go @@ -0,0 +1,25 @@ +package simulation + +import ( + "context" + + "github.com/cosmos/cosmos-sdk/simsx" + "github.com/cosmos/cosmos-sdk/x/auth/types" +) + +func MsgUpdateParamsFactory() simsx.SimMsgFactoryFn[*types.MsgUpdateParams] { + return func(_ context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter) ([]simsx.SimAccount, *types.MsgUpdateParams) { + r := testData.Rand() + params := types.DefaultParams() + params.MaxMemoCharacters = r.Uint64InRange(1, 1000) + params.TxSigLimit = r.Uint64InRange(1, 1000) + params.TxSizeCostPerByte = r.Uint64InRange(1, 1000) + params.SigVerifyCostED25519 = r.Uint64InRange(1, 1000) + params.SigVerifyCostSecp256k1 = r.Uint64InRange(1, 1000) + + return nil, &types.MsgUpdateParams{ + Authority: testData.ModuleAccountAddress(reporter, "gov"), + Params: params, + } + } +} diff --git a/x/auth/simulation/proposals.go b/x/auth/simulation/proposals.go deleted file mode 100644 index 930d9153fd88..000000000000 --- a/x/auth/simulation/proposals.go +++ /dev/null @@ -1,50 +0,0 @@ -package simulation - -import ( - "context" - "math/rand" - - coreaddress "cosmossdk.io/core/address" - - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/types/address" - simtypes "github.com/cosmos/cosmos-sdk/types/simulation" - "github.com/cosmos/cosmos-sdk/x/auth/types" - "github.com/cosmos/cosmos-sdk/x/simulation" -) - -// Simulation operation weights constants -const ( - DefaultWeightMsgUpdateParams int = 100 - - OpWeightMsgUpdateParams = "op_weight_msg_update_params" -) - -// ProposalMsgs defines the module weighted proposals' contents -func ProposalMsgs() []simtypes.WeightedProposalMsg { - return []simtypes.WeightedProposalMsg{ - simulation.NewWeightedProposalMsgX( - OpWeightMsgUpdateParams, - DefaultWeightMsgUpdateParams, - SimulateMsgUpdateParams, - ), - } -} - -// SimulateMsgUpdateParams returns a random MsgUpdateParams -func SimulateMsgUpdateParams(_ context.Context, r *rand.Rand, _ []simtypes.Account, _ coreaddress.Codec) (sdk.Msg, error) { - // use the default gov module account address as authority - var authority sdk.AccAddress = address.Module("gov") - - params := types.DefaultParams() - params.MaxMemoCharacters = uint64(simtypes.RandIntBetween(r, 1, 1000)) - params.TxSigLimit = uint64(simtypes.RandIntBetween(r, 1, 1000)) - params.TxSizeCostPerByte = uint64(simtypes.RandIntBetween(r, 1, 1000)) - params.SigVerifyCostED25519 = uint64(simtypes.RandIntBetween(r, 1, 1000)) - params.SigVerifyCostSecp256k1 = uint64(simtypes.RandIntBetween(r, 1, 1000)) - - return &types.MsgUpdateParams{ - Authority: authority.String(), - Params: params, - }, nil -} diff --git a/x/auth/simulation/proposals_test.go b/x/auth/simulation/proposals_test.go deleted file mode 100644 index f43e105d3056..000000000000 --- a/x/auth/simulation/proposals_test.go +++ /dev/null @@ -1,45 +0,0 @@ -package simulation_test - -import ( - "math/rand" - "testing" - - "gotest.tools/v3/assert" - - codectestutil "github.com/cosmos/cosmos-sdk/codec/testutil" - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/types/address" - simtypes "github.com/cosmos/cosmos-sdk/types/simulation" - "github.com/cosmos/cosmos-sdk/x/auth/simulation" - "github.com/cosmos/cosmos-sdk/x/auth/types" -) - -func TestProposalMsgs(t *testing.T) { - // initialize parameters - s := rand.NewSource(1) - r := rand.New(s) - - accounts := simtypes.RandomAccounts(r, 3) - - // execute ProposalMsgs function - weightedProposalMsgs := simulation.ProposalMsgs() - assert.Assert(t, len(weightedProposalMsgs) == 1) - - w0 := weightedProposalMsgs[0] - - // tests w0 interface: - assert.Equal(t, simulation.OpWeightMsgUpdateParams, w0.AppParamsKey()) - assert.Equal(t, simulation.DefaultWeightMsgUpdateParams, w0.DefaultWeight()) - - msg, err := w0.MsgSimulatorFn()(sdk.Context{}, r, accounts, codectestutil.CodecOptions{}.GetAddressCodec()) - assert.NilError(t, err) - msgUpdateParams, ok := msg.(*types.MsgUpdateParams) - assert.Assert(t, ok) - - assert.Equal(t, sdk.AccAddress(address.Module("gov")).String(), msgUpdateParams.Authority) - assert.Equal(t, uint64(999), msgUpdateParams.Params.MaxMemoCharacters) - assert.Equal(t, uint64(905), msgUpdateParams.Params.TxSigLimit) - assert.Equal(t, uint64(151), msgUpdateParams.Params.TxSizeCostPerByte) - assert.Equal(t, uint64(213), msgUpdateParams.Params.SigVerifyCostED25519) - assert.Equal(t, uint64(539), msgUpdateParams.Params.SigVerifyCostSecp256k1) -} diff --git a/x/auth/testutil/expected_keepers_mocks.go b/x/auth/testutil/expected_keepers_mocks.go index 348a1740378a..e32b234bed54 100644 --- a/x/auth/testutil/expected_keepers_mocks.go +++ b/x/auth/testutil/expected_keepers_mocks.go @@ -134,6 +134,21 @@ func (mr *MockAccountsModKeeperMockRecorder) IsAccountsModuleAccount(ctx, accoun return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsAccountsModuleAccount", reflect.TypeOf((*MockAccountsModKeeper)(nil).IsAccountsModuleAccount), ctx, accountAddr) } +// MigrateLegacyAccount mocks base method. +func (m *MockAccountsModKeeper) MigrateLegacyAccount(ctx context.Context, addr []byte, accNum uint64, accType string, msg transaction.Msg) (transaction.Msg, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "MigrateLegacyAccount", ctx, addr, accNum, accType, msg) + ret0, _ := ret[0].(transaction.Msg) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// MigrateLegacyAccount indicates an expected call of MigrateLegacyAccount. +func (mr *MockAccountsModKeeperMockRecorder) MigrateLegacyAccount(ctx, addr, accNum, accType, msg interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MigrateLegacyAccount", reflect.TypeOf((*MockAccountsModKeeper)(nil).MigrateLegacyAccount), ctx, addr, accNum, accType, msg) +} + // NextAccountNumber mocks base method. func (m *MockAccountsModKeeper) NextAccountNumber(ctx context.Context) (uint64, error) { m.ctrl.T.Helper() @@ -149,6 +164,21 @@ func (mr *MockAccountsModKeeperMockRecorder) NextAccountNumber(ctx interface{}) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NextAccountNumber", reflect.TypeOf((*MockAccountsModKeeper)(nil).NextAccountNumber), ctx) } +// Query mocks base method. +func (m *MockAccountsModKeeper) Query(ctx context.Context, accountAddr []byte, queryRequest transaction.Msg) (transaction.Msg, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Query", ctx, accountAddr, queryRequest) + ret0, _ := ret[0].(transaction.Msg) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Query indicates an expected call of Query. +func (mr *MockAccountsModKeeperMockRecorder) Query(ctx, accountAddr, queryRequest interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Query", reflect.TypeOf((*MockAccountsModKeeper)(nil).Query), ctx, accountAddr, queryRequest) +} + // SendModuleMessage mocks base method. func (m *MockAccountsModKeeper) SendModuleMessage(ctx context.Context, sender []byte, msg transaction.Msg) (transaction.Msg, error) { m.ctrl.T.Helper() diff --git a/x/auth/tx/README.md b/x/auth/tx/README.md index 981f375dc0de..07941952cdc5 100644 --- a/x/auth/tx/README.md +++ b/x/auth/tx/README.md @@ -17,18 +17,28 @@ This document specifies the `x/auth/tx` package of the Cosmos SDK. This package represents the Cosmos SDK implementation of the `client.TxConfig`, `client.TxBuilder`, `client.TxEncoder` and `client.TxDecoder` interfaces. -It contains as well a depinject module and app module the registration of ante/post handler via `runtime` and tx validator via `runtime/v2`. - ## Contents -* [Transactions](#transactions) +* [`x/auth/tx`](#xauthtx) + * [Abstract](#abstract) + * [Contents](#contents) + * [Transactions](#transactions) * [`TxConfig`](#txconfig) * [`TxBuilder`](#txbuilder) * [`TxEncoder`/ `TxDecoder`](#txencoder-txdecoder) -* [Depinject \& App Module](#depinject--app-module) -* [Client](#client) + * [`x/auth/tx/config`](#xauthtxconfig) + * [Storage](#storage) + * [Client](#client) * [CLI](#cli) + * [Query](#query) + * [Transactions](#transactions-1) + * [`encode`](#encode) + * [`decode`](#decode) * [gRPC](#grpc) + * [`TxDecode`](#txdecode) + * [`TxEncode`](#txencode) + * [`TxDecodeAmino`](#txdecodeamino) + * [`TxEncodeAmino`](#txencodeamino) ## Transactions @@ -60,12 +70,21 @@ A `client.TxBuilder` can be accessed with `TxConfig.NewTxBuilder()`. More information about `TxEncoder` and `TxDecoder` can be found [here](https://docs.cosmos.network/main/core/encoding#transaction-encoding). -## Depinject & App Module +## `x/auth/tx/config` + +The `x/auth/tx/config` contains a depinject module. +The depinject module is to outputs the `TxConfig` and `TxConfigOptions` for the app. -The `x/auth/tx/config` contains a depinject module and app module. -The depinject module is there to setup ante/post handlers on an runtime app (via baseapp options) and the tx validator on the runtime/v2 app (via app module). It as well outputs the `TxConfig` and `TxConfigOptions` for the app. +### Storage -The app module is purely there for registering tx validators, due to the design of tx validators (tx validator belong to modules). +This module has no store key. Do not forget to add the module name in the `SkipStoreKeys` runtime config present in the app config. + +```go +SkipStoreKeys: []string{ + authtxconfig.DepinjectModuleName, + validate.ModuleName, +}, +``` ## Client diff --git a/x/auth/tx/aux_test.go b/x/auth/tx/aux_test.go index f1e8dca0879b..9ac871bed501 100644 --- a/x/auth/tx/aux_test.go +++ b/x/auth/tx/aux_test.go @@ -100,7 +100,6 @@ func TestBuilderWithAux(t *testing.T) { {"happy case", func() {}, false}, } for _, tc := range testcases { - tc := tc t.Run(tc.name, func(t *testing.T) { txBuilder, txSig = makeTxBuilder(t) diff --git a/x/auth/tx/config/depinject.go b/x/auth/tx/config/depinject.go index 9c753fbd4729..239ab496517f 100644 --- a/x/auth/tx/config/depinject.go +++ b/x/auth/tx/config/depinject.go @@ -2,8 +2,6 @@ package tx import ( "context" - "errors" - "fmt" gogoproto "github.com/cosmos/gogoproto/proto" "google.golang.org/grpc" @@ -14,9 +12,6 @@ import ( bankv1beta1 "cosmossdk.io/api/cosmos/bank/v1beta1" txconfigv1 "cosmossdk.io/api/cosmos/tx/config/v1" "cosmossdk.io/core/address" - appmodulev2 "cosmossdk.io/core/appmodule/v2" - "cosmossdk.io/core/server" - "cosmossdk.io/core/transaction" "cosmossdk.io/depinject" "cosmossdk.io/depinject/appconfig" txsigning "cosmossdk.io/x/tx/signing" @@ -26,17 +21,11 @@ import ( "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/runtime" - sdk "github.com/cosmos/cosmos-sdk/types" - signingtypes "github.com/cosmos/cosmos-sdk/types/tx/signing" - "github.com/cosmos/cosmos-sdk/x/auth/ante" - "github.com/cosmos/cosmos-sdk/x/auth/ante/unorderedtx" - "github.com/cosmos/cosmos-sdk/x/auth/posthandler" "github.com/cosmos/cosmos-sdk/x/auth/tx" - authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" ) -// flagMinGasPricesV2 is the flag name for the minimum gas prices in the main server v2 component. -const flagMinGasPricesV2 = "server.minimum-gas-prices" +// DepinjectModuleName is the module name used for depinject. +const DepinjectModuleName = "tx" func init() { appconfig.RegisterModule(&txconfigv1.Config{}, @@ -48,34 +37,22 @@ func init() { type ModuleInputs struct { depinject.In - Config *txconfigv1.Config - AddressCodec address.Codec - ValidatorAddressCodec address.ValidatorAddressCodec - Codec codec.Codec - ProtoFileResolver txsigning.ProtoFileResolver - Environment appmodulev2.Environment - // BankKeeper is the expected bank keeper to be passed to AnteHandlers / Tx Validators - ConsensusKeeper ante.ConsensusKeeper - BankKeeper authtypes.BankKeeper `optional:"true"` - MetadataBankKeeper BankKeeper `optional:"true"` - AccountKeeper ante.AccountKeeper `optional:"true"` - FeeGrantKeeper ante.FeegrantKeeper `optional:"true"` - AccountAbstractionKeeper ante.AccountAbstractionKeeper `optional:"true"` - CustomSignModeHandlers func() []txsigning.SignModeHandler `optional:"true"` - CustomGetSigners []txsigning.CustomGetSigner `optional:"true"` - ExtraTxValidators []appmodulev2.TxValidator[transaction.Tx] `optional:"true"` - UnorderedTxManager *unorderedtx.Manager `optional:"true"` - TxFeeChecker ante.TxFeeChecker `optional:"true"` - DynamicConfig server.DynamicConfig `optional:"true"` + Config *txconfigv1.Config + AddressCodec address.Codec + ValidatorAddressCodec address.ValidatorAddressCodec + Codec codec.Codec + ProtoFileResolver txsigning.ProtoFileResolver + CustomSignModeHandlers func() []txsigning.SignModeHandler `optional:"true"` + CustomGetSigners []txsigning.CustomGetSigner `optional:"true"` } type ModuleOutputs struct { depinject.Out - Module appmodulev2.AppModule // This is only useful for chains using server/v2. It setup tx validators that don't belong to other modules. - BaseAppOption runtime.BaseAppOption // This is only useful for chains using baseapp. Server/v2 chains use TxValidator. - TxConfig client.TxConfig - TxConfigOptions tx.ConfigOptions + BaseAppOption runtime.BaseAppOption // This is only useful for chains using baseapp. + TxConfig client.TxConfig + TxConfigOptions tx.ConfigOptions + TxSigningHandlerMap *txsigning.HandlerMap } func ProvideProtoRegistry() txsigning.ProtoFileResolver { @@ -103,123 +80,23 @@ func ProvideModule(in ModuleInputs) ModuleOutputs { txConfigOptions.SigningOptions.CustomGetSigners[mode.MsgType] = mode.Fn } - // enable SIGN_MODE_TEXTUAL only if bank keeper is available - if in.MetadataBankKeeper != nil { - txConfigOptions.EnabledSignModes = append(txConfigOptions.EnabledSignModes, signingtypes.SignMode_SIGN_MODE_TEXTUAL) - txConfigOptions.TextualCoinMetadataQueryFn = NewBankKeeperCoinMetadataQueryFn(in.MetadataBankKeeper) - } - txConfig, err := tx.NewTxConfigWithOptions(in.Codec, txConfigOptions) if err != nil { panic(err) } - svd := ante.NewSigVerificationDecorator( - in.AccountKeeper, - txConfig.SignModeHandler(), - ante.DefaultSigVerificationGasConsumer, - in.AccountAbstractionKeeper, - ) - - var ( - minGasPrices sdk.DecCoins - feeTxValidator *ante.DeductFeeDecorator - unorderedTxValidator *ante.UnorderedTxDecorator - ) - if in.AccountKeeper != nil && in.BankKeeper != nil && in.DynamicConfig != nil { - minGasPricesStr := in.DynamicConfig.GetString(flagMinGasPricesV2) - minGasPrices, err = sdk.ParseDecCoins(minGasPricesStr) - if err != nil { - panic(fmt.Sprintf("invalid minimum gas prices: %v", err)) - } - - feeTxValidator = ante.NewDeductFeeDecorator(in.AccountKeeper, in.BankKeeper, in.FeeGrantKeeper, in.TxFeeChecker) - feeTxValidator.SetMinGasPrices(minGasPrices) // set min gas price in deduct fee decorator - } - - if in.UnorderedTxManager != nil { - unorderedTxValidator = ante.NewUnorderedTxDecorator(unorderedtx.DefaultMaxTimeoutDuration, in.UnorderedTxManager, in.Environment, ante.DefaultSha256Cost) - } - return ModuleOutputs{ - Module: NewAppModule(svd, feeTxValidator, unorderedTxValidator, in.ExtraTxValidators...), - BaseAppOption: newBaseAppOption(txConfig, in), - TxConfig: txConfig, - TxConfigOptions: txConfigOptions, - } -} - -// newBaseAppOption returns baseapp option that sets the ante handler and post handler -// and set the tx encoder and decoder on baseapp. -func newBaseAppOption(txConfig client.TxConfig, in ModuleInputs) func(app *baseapp.BaseApp) { - return func(app *baseapp.BaseApp) { - // AnteHandlers - if !in.Config.SkipAnteHandler { - anteHandler, err := newAnteHandler(txConfig, in) - if err != nil { - panic(err) - } - app.SetAnteHandler(anteHandler) - } - - // PostHandlers - if !in.Config.SkipPostHandler { - // In v0.46, the SDK introduces _postHandlers_. PostHandlers are like - // antehandlers, but are run _after_ the `runMsgs` execution. They are also - // defined as a chain, and have the same signature as antehandlers. - // - // In baseapp, postHandlers are run in the same store branch as `runMsgs`, - // meaning that both `runMsgs` and `postHandler` state will be committed if - // both are successful, and both will be reverted if any of the two fails. - // - // The SDK exposes a default empty postHandlers chain. - // - // Please note that changing any of the anteHandler or postHandler chain is - // likely to be a state-machine breaking change, which needs a coordinated - // upgrade. - postHandler, err := posthandler.NewPostHandler( - posthandler.HandlerOptions{}, - ) - if err != nil { - panic(err) - } - app.SetPostHandler(postHandler) - } - - // TxDecoder/TxEncoder - app.SetTxDecoder(txConfig.TxDecoder()) - app.SetTxEncoder(txConfig.TxEncoder()) - } -} - -func newAnteHandler(txConfig client.TxConfig, in ModuleInputs) (sdk.AnteHandler, error) { - if in.BankKeeper == nil { - return nil, errors.New("both AccountKeeper and BankKeeper are required") - } - - anteHandler, err := ante.NewAnteHandler( - ante.HandlerOptions{ - Environment: in.Environment, - AccountKeeper: in.AccountKeeper, - ConsensusKeeper: in.ConsensusKeeper, - BankKeeper: in.BankKeeper, - SignModeHandler: txConfig.SignModeHandler(), - FeegrantKeeper: in.FeeGrantKeeper, - SigGasConsumer: ante.DefaultSigVerificationGasConsumer, - UnorderedTxManager: in.UnorderedTxManager, + BaseAppOption: func(app *baseapp.BaseApp) { + app.SetTxDecoder(txConfig.TxDecoder()) + app.SetTxEncoder(txConfig.TxEncoder()) }, - ) - if err != nil { - return nil, fmt.Errorf("failed to create ante handler: %w", err) + TxConfig: txConfig, + TxConfigOptions: txConfigOptions, + TxSigningHandlerMap: txConfig.SignModeHandler(), } - - return anteHandler, nil } -// NewBankKeeperCoinMetadataQueryFn creates a new Textual struct using the given -// BankKeeper to retrieve coin metadata. -// -// This function should be used in the server (app.go) and is already injected thanks to app wiring for app_di. +// NewBankKeeperCoinMetadataQueryFn creates a new Textual struct using the given BankKeeper to retrieve coin metadata. func NewBankKeeperCoinMetadataQueryFn(bk BankKeeper) textual.CoinMetadataQueryFn { return func(ctx context.Context, denom string) (*bankv1beta1.Metadata, error) { res, err := bk.DenomMetadataV2(ctx, &bankv1beta1.QueryDenomMetadataRequest{Denom: denom}) diff --git a/x/auth/tx/query.go b/x/auth/tx/query.go index c49ddfa25458..54af403316fb 100644 --- a/x/auth/tx/query.go +++ b/x/auth/tx/query.go @@ -114,8 +114,6 @@ func getBlocksForTxResults(clientCtx client.Context, resTxs []*coretypes.ResultT resBlocks := make(map[int64]*coretypes.ResultBlock) for _, resTx := range resTxs { - resTx := resTx - if _, ok := resBlocks[resTx.Height]; !ok { resBlock, err := node.Block(context.Background(), &resTx.Height) if err != nil { diff --git a/x/auth/types/account_test.go b/x/auth/types/account_test.go index b4fadfa391a7..f0cc88ae85fa 100644 --- a/x/auth/types/account_test.go +++ b/x/auth/types/account_test.go @@ -84,8 +84,6 @@ func TestGenesisAccountValidate(t *testing.T) { } for _, tt := range tests { - tt := tt - t.Run(tt.name, func(t *testing.T) { require.Equal(t, tt.expErr, tt.acc.Validate() != nil) }) @@ -151,7 +149,6 @@ func TestValidate(t *testing.T) { }, } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { err := tt.acc.Validate() require.Equal(t, tt.expErr, err) diff --git a/x/auth/types/accounts.pb.go b/x/auth/types/accounts.pb.go new file mode 100644 index 000000000000..ee8ce1e00e09 --- /dev/null +++ b/x/auth/types/accounts.pb.go @@ -0,0 +1,523 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: cosmos/auth/v1beta1/accounts.proto + +package types + +import ( + fmt "fmt" + proto "github.com/cosmos/gogoproto/proto" + any "github.com/cosmos/gogoproto/types/any" + io "io" + math "math" + math_bits "math/bits" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// QueryLegacyAccount defines a query that can be implemented by an x/account +// to return an auth understandable representation of an account. +// This query is only used for accounts retro-compatibility at gRPC +// level, the state machine must not make any assumptions around this. +type QueryLegacyAccount struct { +} + +func (m *QueryLegacyAccount) Reset() { *m = QueryLegacyAccount{} } +func (m *QueryLegacyAccount) String() string { return proto.CompactTextString(m) } +func (*QueryLegacyAccount) ProtoMessage() {} +func (*QueryLegacyAccount) Descriptor() ([]byte, []int) { + return fileDescriptor_25696478f9b3e7f4, []int{0} +} +func (m *QueryLegacyAccount) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryLegacyAccount) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryLegacyAccount.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 *QueryLegacyAccount) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryLegacyAccount.Merge(m, src) +} +func (m *QueryLegacyAccount) XXX_Size() int { + return m.Size() +} +func (m *QueryLegacyAccount) XXX_DiscardUnknown() { + xxx_messageInfo_QueryLegacyAccount.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryLegacyAccount proto.InternalMessageInfo + +// QueryLegacyAccountResponse defines the response type of the +// `QueryLegacyAccount` query. +type QueryLegacyAccountResponse struct { + // account represents the google.Protobuf.Any wrapped account + // the type wrapped by the any does not need to comply with the + // sdk.AccountI interface. + Account *any.Any `protobuf:"bytes,1,opt,name=account,proto3" json:"account,omitempty"` + // base represents the account as a BaseAccount, this can return + // nil if the account cannot be represented as a BaseAccount. + // This is used in the gRPC QueryAccountInfo method. + Base *BaseAccount `protobuf:"bytes,2,opt,name=base,proto3" json:"base,omitempty"` +} + +func (m *QueryLegacyAccountResponse) Reset() { *m = QueryLegacyAccountResponse{} } +func (m *QueryLegacyAccountResponse) String() string { return proto.CompactTextString(m) } +func (*QueryLegacyAccountResponse) ProtoMessage() {} +func (*QueryLegacyAccountResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_25696478f9b3e7f4, []int{1} +} +func (m *QueryLegacyAccountResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryLegacyAccountResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryLegacyAccountResponse.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 *QueryLegacyAccountResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryLegacyAccountResponse.Merge(m, src) +} +func (m *QueryLegacyAccountResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryLegacyAccountResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryLegacyAccountResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryLegacyAccountResponse proto.InternalMessageInfo + +func (m *QueryLegacyAccountResponse) GetAccount() *any.Any { + if m != nil { + return m.Account + } + return nil +} + +func (m *QueryLegacyAccountResponse) GetBase() *BaseAccount { + if m != nil { + return m.Base + } + return nil +} + +func init() { + proto.RegisterType((*QueryLegacyAccount)(nil), "cosmos.auth.v1beta1.QueryLegacyAccount") + proto.RegisterType((*QueryLegacyAccountResponse)(nil), "cosmos.auth.v1beta1.QueryLegacyAccountResponse") +} + +func init() { + proto.RegisterFile("cosmos/auth/v1beta1/accounts.proto", fileDescriptor_25696478f9b3e7f4) +} + +var fileDescriptor_25696478f9b3e7f4 = []byte{ + // 246 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0xcf, 0xb1, 0x4e, 0xc3, 0x30, + 0x10, 0x06, 0xe0, 0x18, 0x21, 0x90, 0xcc, 0x16, 0x3a, 0x94, 0x0c, 0x56, 0x95, 0x09, 0x06, 0xce, + 0x2a, 0xf0, 0x02, 0x2d, 0x2b, 0x0b, 0x1d, 0xd9, 0x6c, 0x63, 0x52, 0x04, 0xcd, 0x45, 0x3d, 0x1b, + 0xe1, 0x95, 0x27, 0xe0, 0xb1, 0x18, 0x3b, 0x32, 0xa2, 0xe4, 0x45, 0x50, 0xed, 0x64, 0x6a, 0x26, + 0x4b, 0xf6, 0xe7, 0xbb, 0xff, 0xe7, 0xa5, 0x41, 0xda, 0x20, 0x49, 0xe5, 0xdd, 0x5a, 0x7e, 0xcc, + 0xb5, 0x75, 0x6a, 0x2e, 0x95, 0x31, 0xe8, 0x6b, 0x47, 0xd0, 0x6c, 0xd1, 0x61, 0x7e, 0x9e, 0x0c, + 0xec, 0x0d, 0xf4, 0xa6, 0xb8, 0xa8, 0x10, 0xab, 0x77, 0x2b, 0x23, 0xd1, 0xfe, 0x45, 0xaa, 0x3a, + 0x24, 0x5f, 0x88, 0xd1, 0x99, 0xfb, 0xcf, 0xf1, 0xbd, 0x9c, 0xf0, 0xfc, 0xd1, 0xdb, 0x6d, 0x78, + 0xb0, 0x95, 0x32, 0x61, 0x91, 0x96, 0x95, 0x5f, 0x8c, 0x17, 0x87, 0xd7, 0x2b, 0x4b, 0x0d, 0xd6, + 0x64, 0x73, 0xe0, 0xa7, 0x7d, 0xac, 0x29, 0x9b, 0xb1, 0xcb, 0xb3, 0x9b, 0x09, 0xa4, 0x04, 0x30, + 0x24, 0x80, 0x45, 0x1d, 0x56, 0x03, 0xca, 0xef, 0xf8, 0xb1, 0x56, 0x64, 0xa7, 0x47, 0x11, 0xcf, + 0x60, 0xa4, 0x03, 0x2c, 0x15, 0xd9, 0x61, 0x4f, 0xd4, 0xcb, 0xfb, 0x9f, 0x56, 0xb0, 0x5d, 0x2b, + 0xd8, 0x5f, 0x2b, 0xd8, 0x77, 0x27, 0xb2, 0x5d, 0x27, 0xb2, 0xdf, 0x4e, 0x64, 0x4f, 0x57, 0xd5, + 0xab, 0x5b, 0x7b, 0x0d, 0x06, 0x37, 0xb2, 0xef, 0x97, 0x8e, 0x6b, 0x7a, 0x7e, 0x93, 0x9f, 0xa9, + 0xac, 0x0b, 0x8d, 0x25, 0x7d, 0x12, 0x13, 0xdd, 0xfe, 0x07, 0x00, 0x00, 0xff, 0xff, 0x5c, 0xc3, + 0xec, 0xca, 0x5c, 0x01, 0x00, 0x00, +} + +func (m *QueryLegacyAccount) 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 *QueryLegacyAccount) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryLegacyAccount) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *QueryLegacyAccountResponse) 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 *QueryLegacyAccountResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryLegacyAccountResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Base != nil { + { + size, err := m.Base.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintAccounts(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + if m.Account != nil { + { + size, err := m.Account.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintAccounts(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func encodeVarintAccounts(dAtA []byte, offset int, v uint64) int { + offset -= sovAccounts(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *QueryLegacyAccount) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *QueryLegacyAccountResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Account != nil { + l = m.Account.Size() + n += 1 + l + sovAccounts(uint64(l)) + } + if m.Base != nil { + l = m.Base.Size() + n += 1 + l + sovAccounts(uint64(l)) + } + return n +} + +func sovAccounts(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozAccounts(x uint64) (n int) { + return sovAccounts(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *QueryLegacyAccount) 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 ErrIntOverflowAccounts + } + 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: QueryLegacyAccount: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryLegacyAccount: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipAccounts(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthAccounts + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryLegacyAccountResponse) 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 ErrIntOverflowAccounts + } + 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: QueryLegacyAccountResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryLegacyAccountResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Account", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowAccounts + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthAccounts + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthAccounts + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Account == nil { + m.Account = &any.Any{} + } + if err := m.Account.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Base", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowAccounts + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthAccounts + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthAccounts + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Base == nil { + m.Base = &BaseAccount{} + } + if err := m.Base.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipAccounts(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthAccounts + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipAccounts(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowAccounts + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowAccounts + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowAccounts + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthAccounts + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupAccounts + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthAccounts + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthAccounts = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowAccounts = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupAccounts = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/auth/types/codec.go b/x/auth/types/codec.go index 7f429d3b945b..882aaeb7d160 100644 --- a/x/auth/types/codec.go +++ b/x/auth/types/codec.go @@ -59,5 +59,6 @@ func RegisterInterfaces(registrar registry.InterfaceRegistrar) { registrar.RegisterImplementations((*coretransaction.Msg)(nil), &MsgUpdateParams{}, &MsgNonAtomicExec{}, + &MsgMigrateAccount{}, ) } diff --git a/x/auth/types/expected_keepers.go b/x/auth/types/expected_keepers.go index 7fb82e89ed8a..6edca889809d 100644 --- a/x/auth/types/expected_keepers.go +++ b/x/auth/types/expected_keepers.go @@ -21,7 +21,23 @@ type AccountsModKeeper interface { IsAccountsModuleAccount(ctx context.Context, accountAddr []byte) bool NextAccountNumber(ctx context.Context) (accNum uint64, err error) + // Query is used to query an account + Query( + ctx context.Context, + accountAddr []byte, + queryRequest transaction.Msg, + ) (transaction.Msg, error) + // InitAccountNumberSeqUnsafe is use to set accounts module account number with value // of auth module current account number InitAccountNumberSeqUnsafe(ctx context.Context, currentAccNum uint64) error + + // MigrateLegacyAccount migrates the given account to an x/accounts' account. + MigrateLegacyAccount( + ctx context.Context, + addr []byte, // The current address of the account + accNum uint64, // The current account number + accType string, // The account type to migrate to + msg transaction.Msg, // The init msg of the account type we're migrating to + ) (transaction.Msg, error) } diff --git a/x/auth/types/params_test.go b/x/auth/types/params_test.go index 587778e1f3d9..9c776c5509e2 100644 --- a/x/auth/types/params_test.go +++ b/x/auth/types/params_test.go @@ -37,7 +37,6 @@ func TestParams_Validate(t *testing.T) { types.DefaultSigVerifyCostED25519, types.DefaultSigVerifyCostSecp256k1), errors.New("invalid tx size cost per byte: 0")}, } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { got := tt.params.Validate() if tt.wantErr == nil { diff --git a/x/auth/types/permissions_test.go b/x/auth/types/permissions_test.go index de5c25645769..78133007dac7 100644 --- a/x/auth/types/permissions_test.go +++ b/x/auth/types/permissions_test.go @@ -41,7 +41,6 @@ func TestValidatePermissions(t *testing.T) { } for i, tc := range cases { - i, tc := i, tc t.Run(tc.name, func(t *testing.T) { err := validatePermissions(tc.permissions...) if tc.expectPass { diff --git a/x/auth/types/tx.pb.go b/x/auth/types/tx.pb.go index ac7597d04746..8fbc233a8376 100644 --- a/x/auth/types/tx.pb.go +++ b/x/auth/types/tx.pb.go @@ -279,53 +279,172 @@ func (m *MsgNonAtomicExecResponse) GetResults() []*NonAtomicExecResult { return nil } +// MsgMigrateAccount defines a message which allows users to migrate from BaseAccount +// to other x/accounts types. +type MsgMigrateAccount struct { + Signer string `protobuf:"bytes,1,opt,name=signer,proto3" json:"signer,omitempty"` + AccountType string `protobuf:"bytes,2,opt,name=account_type,json=accountType,proto3" json:"account_type,omitempty"` + AccountInitMsg *any.Any `protobuf:"bytes,3,opt,name=account_init_msg,json=accountInitMsg,proto3" json:"account_init_msg,omitempty"` +} + +func (m *MsgMigrateAccount) Reset() { *m = MsgMigrateAccount{} } +func (m *MsgMigrateAccount) String() string { return proto.CompactTextString(m) } +func (*MsgMigrateAccount) ProtoMessage() {} +func (*MsgMigrateAccount) Descriptor() ([]byte, []int) { + return fileDescriptor_c2d62bd9c4c212e5, []int{5} +} +func (m *MsgMigrateAccount) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgMigrateAccount) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgMigrateAccount.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 *MsgMigrateAccount) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgMigrateAccount.Merge(m, src) +} +func (m *MsgMigrateAccount) XXX_Size() int { + return m.Size() +} +func (m *MsgMigrateAccount) XXX_DiscardUnknown() { + xxx_messageInfo_MsgMigrateAccount.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgMigrateAccount proto.InternalMessageInfo + +func (m *MsgMigrateAccount) GetSigner() string { + if m != nil { + return m.Signer + } + return "" +} + +func (m *MsgMigrateAccount) GetAccountType() string { + if m != nil { + return m.AccountType + } + return "" +} + +func (m *MsgMigrateAccount) GetAccountInitMsg() *any.Any { + if m != nil { + return m.AccountInitMsg + } + return nil +} + +// MsgMigrateAccountResponse defines the response given when migrating to +// an x/accounts account. +type MsgMigrateAccountResponse struct { + // init_response defines the response returned by the x/account account + // initialization. + InitResponse *any.Any `protobuf:"bytes,1,opt,name=init_response,json=initResponse,proto3" json:"init_response,omitempty"` +} + +func (m *MsgMigrateAccountResponse) Reset() { *m = MsgMigrateAccountResponse{} } +func (m *MsgMigrateAccountResponse) String() string { return proto.CompactTextString(m) } +func (*MsgMigrateAccountResponse) ProtoMessage() {} +func (*MsgMigrateAccountResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_c2d62bd9c4c212e5, []int{6} +} +func (m *MsgMigrateAccountResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgMigrateAccountResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgMigrateAccountResponse.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 *MsgMigrateAccountResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgMigrateAccountResponse.Merge(m, src) +} +func (m *MsgMigrateAccountResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgMigrateAccountResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgMigrateAccountResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgMigrateAccountResponse proto.InternalMessageInfo + +func (m *MsgMigrateAccountResponse) GetInitResponse() *any.Any { + if m != nil { + return m.InitResponse + } + return nil +} + func init() { proto.RegisterType((*MsgUpdateParams)(nil), "cosmos.auth.v1beta1.MsgUpdateParams") proto.RegisterType((*MsgUpdateParamsResponse)(nil), "cosmos.auth.v1beta1.MsgUpdateParamsResponse") proto.RegisterType((*MsgNonAtomicExec)(nil), "cosmos.auth.v1beta1.MsgNonAtomicExec") proto.RegisterType((*NonAtomicExecResult)(nil), "cosmos.auth.v1beta1.NonAtomicExecResult") proto.RegisterType((*MsgNonAtomicExecResponse)(nil), "cosmos.auth.v1beta1.MsgNonAtomicExecResponse") + proto.RegisterType((*MsgMigrateAccount)(nil), "cosmos.auth.v1beta1.MsgMigrateAccount") + proto.RegisterType((*MsgMigrateAccountResponse)(nil), "cosmos.auth.v1beta1.MsgMigrateAccountResponse") } func init() { proto.RegisterFile("cosmos/auth/v1beta1/tx.proto", fileDescriptor_c2d62bd9c4c212e5) } var fileDescriptor_c2d62bd9c4c212e5 = []byte{ - // 548 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x53, 0xcf, 0x8f, 0xd2, 0x40, - 0x14, 0x66, 0xdc, 0x1f, 0x86, 0x41, 0xb3, 0x5a, 0x48, 0x16, 0x59, 0x53, 0xb1, 0xd1, 0x04, 0x89, - 0x4c, 0x17, 0x34, 0x9a, 0x70, 0x30, 0x01, 0xb3, 0xf1, 0x84, 0x31, 0x35, 0x7b, 0xf1, 0xa0, 0x29, - 0x30, 0xce, 0x36, 0x6e, 0x3b, 0x4d, 0xdf, 0xb0, 0xc2, 0xcd, 0x78, 0xf4, 0xe4, 0xd1, 0x3f, 0xc1, - 0x23, 0x07, 0xfe, 0x88, 0xcd, 0x9e, 0x36, 0x9c, 0x3c, 0x19, 0x03, 0x07, 0x2e, 0xfe, 0x11, 0xa6, - 0x33, 0x53, 0x09, 0x6c, 0x8d, 0x7b, 0x69, 0x3b, 0xf3, 0x7d, 0xef, 0xbd, 0xef, 0xbd, 0xef, 0x15, - 0xdf, 0xee, 0x71, 0xf0, 0x39, 0xd8, 0xee, 0x40, 0x1c, 0xd9, 0x27, 0xf5, 0x2e, 0x15, 0x6e, 0xdd, - 0x16, 0x43, 0x12, 0x46, 0x5c, 0x70, 0x23, 0xaf, 0x50, 0x12, 0xa3, 0x44, 0xa3, 0xa5, 0x02, 0xe3, - 0x8c, 0x4b, 0xdc, 0x8e, 0xbf, 0x14, 0xb5, 0x74, 0x8b, 0x71, 0xce, 0x8e, 0xa9, 0x2d, 0x4f, 0xdd, - 0xc1, 0x7b, 0xdb, 0x0d, 0x46, 0x09, 0xa4, 0xb2, 0xbc, 0x53, 0x31, 0x3a, 0xa5, 0x82, 0x76, 0x75, - 0x79, 0x1f, 0x98, 0x7d, 0x52, 0x8f, 0x5f, 0x1a, 0xb8, 0xe9, 0xfa, 0x5e, 0xc0, 0x6d, 0xf9, 0xd4, - 0x57, 0x66, 0x9a, 0x54, 0xa9, 0x4c, 0xe2, 0xd6, 0x14, 0xe1, 0x9d, 0x0e, 0xb0, 0xc3, 0xb0, 0xef, - 0x0a, 0xfa, 0xca, 0x8d, 0x5c, 0x1f, 0x8c, 0x27, 0x38, 0x1b, 0x33, 0x78, 0xe4, 0x89, 0x51, 0x11, - 0x95, 0x51, 0x25, 0xdb, 0x2e, 0x4e, 0x27, 0xb5, 0x82, 0x16, 0xd1, 0xea, 0xf7, 0x23, 0x0a, 0xf0, - 0x5a, 0x44, 0x5e, 0xc0, 0x9c, 0x25, 0xd5, 0x78, 0x86, 0xb7, 0x43, 0x99, 0xa1, 0x78, 0xa5, 0x8c, - 0x2a, 0xb9, 0xc6, 0x1e, 0x49, 0x99, 0x04, 0x51, 0x45, 0xda, 0xd9, 0xd3, 0x9f, 0x77, 0x32, 0xdf, - 0x17, 0xe3, 0x2a, 0x72, 0x74, 0x54, 0xf3, 0xc5, 0x74, 0x52, 0xdb, 0x51, 0x21, 0x35, 0xe8, 0x7f, - 0x28, 0xef, 0x93, 0xc7, 0x4f, 0x3f, 0x2f, 0xc6, 0xd5, 0x65, 0x89, 0x2f, 0x8b, 0x71, 0xf5, 0xee, - 0x92, 0x61, 0x0f, 0x55, 0x5f, 0x6b, 0x0d, 0x58, 0x04, 0xef, 0xae, 0x5d, 0x39, 0x14, 0x42, 0x1e, - 0x00, 0x6d, 0xe6, 0x53, 0x6a, 0x58, 0xdf, 0x10, 0xbe, 0xd1, 0x01, 0xf6, 0x92, 0x07, 0x2d, 0xc1, - 0x7d, 0xaf, 0x77, 0x30, 0xa4, 0x3d, 0x63, 0x1f, 0x6f, 0x83, 0xc7, 0x02, 0x1a, 0xfd, 0x77, 0x04, - 0x9a, 0x67, 0x1c, 0xe0, 0x4d, 0x1f, 0x58, 0xdc, 0xfd, 0x46, 0x25, 0xd7, 0x28, 0x10, 0x65, 0x2e, - 0x49, 0xcc, 0x25, 0xad, 0x60, 0xd4, 0xde, 0x3b, 0x9b, 0xd4, 0xb4, 0x7f, 0xa4, 0xeb, 0x02, 0xfd, - 0x3b, 0x96, 0x0e, 0x30, 0x47, 0x86, 0x37, 0x73, 0x71, 0xcf, 0x3a, 0xa7, 0x75, 0x88, 0xf3, 0x2b, - 0xb2, 0x1c, 0x0a, 0x83, 0x63, 0x61, 0x14, 0xf0, 0x16, 0x8d, 0x22, 0xae, 0xb5, 0x39, 0xea, 0x60, - 0x54, 0xf0, 0x66, 0x44, 0x21, 0xd4, 0xe3, 0x4f, 0x15, 0xe0, 0x48, 0x86, 0xf5, 0x16, 0x17, 0xd7, - 0x1b, 0x4e, 0x46, 0x64, 0xb4, 0xf1, 0xd5, 0x48, 0x56, 0x81, 0x22, 0x92, 0x9d, 0x54, 0x52, 0x7d, - 0x4c, 0x91, 0xe5, 0x24, 0x81, 0x8d, 0xdf, 0x08, 0x6f, 0x74, 0x80, 0x19, 0x1f, 0xf1, 0xb5, 0x95, - 0xd5, 0xba, 0x97, 0x9a, 0x6a, 0xcd, 0xac, 0xd2, 0xc3, 0xcb, 0xb0, 0x12, 0xbd, 0x56, 0xfe, 0xec, - 0xa2, 0xa5, 0x06, 0xc5, 0xd7, 0x57, 0xed, 0xbc, 0xff, 0xaf, 0x9c, 0x2b, 0xb4, 0x52, 0xed, 0x52, - 0xb4, 0xa4, 0x76, 0x69, 0xeb, 0x53, 0xbc, 0xc1, 0xed, 0xe7, 0xa7, 0x33, 0x13, 0x9d, 0xcf, 0x4c, - 0xf4, 0x6b, 0x66, 0xa2, 0xaf, 0x73, 0x33, 0x73, 0x3e, 0x37, 0x33, 0x3f, 0xe6, 0x66, 0xe6, 0xcd, - 0x03, 0xe6, 0x89, 0xa3, 0x41, 0x97, 0xf4, 0xb8, 0xaf, 0x7f, 0x62, 0xfb, 0xe2, 0xfe, 0x8a, 0x51, - 0x48, 0xa1, 0xbb, 0x2d, 0x7d, 0x7a, 0xf4, 0x27, 0x00, 0x00, 0xff, 0xff, 0x4a, 0xdf, 0x75, 0x60, - 0x5e, 0x04, 0x00, 0x00, + // 667 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x54, 0xcb, 0x6e, 0xd3, 0x40, + 0x14, 0x8d, 0xfb, 0x42, 0x99, 0xf4, 0xe9, 0x44, 0xaa, 0xeb, 0x22, 0xd3, 0x9a, 0x87, 0x42, 0x45, + 0xc6, 0x7d, 0x20, 0x10, 0x59, 0x54, 0x4a, 0x50, 0x85, 0x58, 0x18, 0x21, 0x43, 0x59, 0xb0, 0xa0, + 0x72, 0x9c, 0x61, 0x6a, 0x51, 0x7b, 0xac, 0x99, 0x49, 0x69, 0x76, 0x88, 0x25, 0x2b, 0x96, 0x7c, + 0x02, 0xcb, 0x2e, 0xfa, 0x11, 0x55, 0x57, 0x55, 0x17, 0x88, 0x0d, 0x08, 0xb5, 0x8b, 0xfe, 0x06, + 0xf2, 0x78, 0xdc, 0xe2, 0xd4, 0x81, 0x88, 0x4d, 0x62, 0xcf, 0x3d, 0xf7, 0xde, 0x73, 0xce, 0xbd, + 0x63, 0x70, 0xdd, 0x23, 0x2c, 0x20, 0xcc, 0x72, 0x3b, 0x7c, 0xdb, 0xda, 0x5d, 0x69, 0x21, 0xee, + 0xae, 0x58, 0x7c, 0x0f, 0x46, 0x94, 0x70, 0xa2, 0x96, 0x93, 0x28, 0x8c, 0xa3, 0x50, 0x46, 0xf5, + 0x0a, 0x26, 0x98, 0x88, 0xb8, 0x15, 0x3f, 0x25, 0x50, 0x7d, 0x0e, 0x13, 0x82, 0x77, 0x90, 0x25, + 0xde, 0x5a, 0x9d, 0xb7, 0x96, 0x1b, 0x76, 0xd3, 0x50, 0x52, 0x65, 0x2b, 0xc9, 0x91, 0x25, 0x93, + 0xd0, 0xac, 0x6c, 0x1f, 0x30, 0x6c, 0xed, 0xae, 0xc4, 0x7f, 0x32, 0x30, 0xe3, 0x06, 0x7e, 0x48, + 0x2c, 0xf1, 0x2b, 0x8f, 0x8c, 0x3c, 0xaa, 0x82, 0x99, 0x88, 0x9b, 0x27, 0x0a, 0x98, 0xb2, 0x19, + 0xde, 0x8c, 0xda, 0x2e, 0x47, 0xcf, 0x5d, 0xea, 0x06, 0x4c, 0x7d, 0x00, 0x8a, 0x31, 0x82, 0x50, + 0x9f, 0x77, 0x35, 0x65, 0x41, 0xa9, 0x16, 0x9b, 0xda, 0xc9, 0x41, 0xad, 0x22, 0x49, 0x34, 0xda, + 0x6d, 0x8a, 0x18, 0x7b, 0xc1, 0xa9, 0x1f, 0x62, 0xe7, 0x12, 0xaa, 0xae, 0x83, 0xb1, 0x48, 0x54, + 0xd0, 0x86, 0x16, 0x94, 0x6a, 0x69, 0x75, 0x1e, 0xe6, 0x38, 0x01, 0x93, 0x26, 0xcd, 0xe2, 0xe1, + 0xcf, 0x1b, 0x85, 0xaf, 0xe7, 0xfb, 0x4b, 0x8a, 0x23, 0xb3, 0xea, 0x4f, 0x4e, 0x0e, 0x6a, 0x53, + 0x49, 0x4a, 0x8d, 0xb5, 0xdf, 0x2d, 0x2c, 0xc3, 0xfb, 0x0f, 0x3f, 0x9e, 0xef, 0x2f, 0x5d, 0xb6, + 0xf8, 0x74, 0xbe, 0xbf, 0xb4, 0x78, 0x89, 0xb0, 0xf6, 0x12, 0x5d, 0x3d, 0x02, 0x4c, 0x08, 0x66, + 0x7b, 0x8e, 0x1c, 0xc4, 0x22, 0x12, 0x32, 0x54, 0x2f, 0xe7, 0xf4, 0x30, 0xbf, 0x28, 0x60, 0xda, + 0x66, 0xf8, 0x19, 0x09, 0x1b, 0x9c, 0x04, 0xbe, 0xb7, 0xb1, 0x87, 0x3c, 0x75, 0x19, 0x8c, 0x31, + 0x1f, 0x87, 0x88, 0xfe, 0xd3, 0x02, 0x89, 0x53, 0x37, 0xc0, 0x48, 0xc0, 0x70, 0xac, 0x7e, 0xb8, + 0x5a, 0x5a, 0xad, 0xc0, 0x64, 0xb8, 0x30, 0x1d, 0x2e, 0x6c, 0x84, 0xdd, 0xe6, 0xfc, 0xd1, 0x41, + 0x4d, 0xce, 0x0f, 0xb6, 0x5c, 0x86, 0x2e, 0x6c, 0xb1, 0x19, 0x76, 0x44, 0x7a, 0xbd, 0x14, 0x6b, + 0x96, 0x35, 0xcd, 0x4d, 0x50, 0xce, 0xd0, 0x72, 0x10, 0xeb, 0xec, 0x70, 0xb5, 0x02, 0x46, 0x11, + 0xa5, 0x44, 0x72, 0x73, 0x92, 0x17, 0xb5, 0x0a, 0x46, 0x28, 0x62, 0x91, 0xb4, 0x3f, 0x97, 0x80, + 0x23, 0x10, 0xe6, 0x1b, 0xa0, 0xf5, 0x0a, 0x4e, 0x2d, 0x52, 0x9b, 0xe0, 0x1a, 0x15, 0x5d, 0x98, + 0xa6, 0x08, 0x25, 0xd5, 0xdc, 0x39, 0xe6, 0xd0, 0x72, 0xd2, 0x44, 0xf3, 0x87, 0x02, 0x66, 0x6c, + 0x86, 0x6d, 0x1f, 0x53, 0x97, 0xa3, 0x86, 0xe7, 0x91, 0x4e, 0xc8, 0xff, 0xc3, 0xd2, 0x45, 0x30, + 0xee, 0x26, 0xc9, 0x5b, 0xbc, 0x1b, 0x21, 0xa1, 0xac, 0xe8, 0x94, 0xe4, 0xd9, 0xcb, 0x6e, 0x84, + 0xd4, 0x75, 0x30, 0x9d, 0x42, 0xfc, 0xd0, 0xe7, 0x5b, 0x01, 0xc3, 0xda, 0xf0, 0x5f, 0x0c, 0x98, + 0x94, 0xe8, 0xa7, 0xa1, 0xcf, 0x6d, 0x86, 0xeb, 0x6b, 0x7f, 0xd8, 0x1d, 0xef, 0xd7, 0xcd, 0xdc, + 0xfd, 0xca, 0x2a, 0x31, 0x5f, 0x81, 0xb9, 0x2b, 0x87, 0x17, 0x06, 0x3e, 0x02, 0x13, 0x82, 0x09, + 0x95, 0x07, 0x42, 0x6d, 0x3f, 0x3a, 0xe3, 0x31, 0x34, 0x4d, 0x5d, 0xfd, 0x36, 0x04, 0x86, 0x6d, + 0x86, 0xd5, 0xf7, 0x60, 0x3c, 0x73, 0x25, 0x6f, 0xe5, 0x8e, 0xa0, 0x67, 0xc9, 0xf5, 0x7b, 0x83, + 0xa0, 0xd2, 0x5e, 0x66, 0xf9, 0xe8, 0xea, 0x55, 0x50, 0x11, 0x98, 0xc8, 0x5e, 0x83, 0xdb, 0xfd, + 0x6a, 0x66, 0x60, 0x7a, 0x6d, 0x20, 0xd8, 0x85, 0x45, 0xdb, 0x60, 0xb2, 0x67, 0x37, 0xee, 0xf4, + 0x2b, 0x90, 0xc5, 0xe9, 0x70, 0x30, 0x5c, 0xda, 0x49, 0x1f, 0xfd, 0x10, 0x7f, 0x63, 0x9a, 0x8f, + 0x0f, 0x4f, 0x0d, 0xe5, 0xf8, 0xd4, 0x50, 0x7e, 0x9d, 0x1a, 0xca, 0xe7, 0x33, 0xa3, 0x70, 0x7c, + 0x66, 0x14, 0xbe, 0x9f, 0x19, 0x85, 0xd7, 0x77, 0xb1, 0xcf, 0xb7, 0x3b, 0x2d, 0xe8, 0x91, 0x40, + 0x7e, 0x66, 0xad, 0xab, 0x1b, 0x10, 0x2f, 0x1f, 0x6b, 0x8d, 0x89, 0xc9, 0xad, 0xfd, 0x0e, 0x00, + 0x00, 0xff, 0xff, 0xc2, 0x24, 0xb6, 0x0e, 0x00, 0x06, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -345,6 +464,8 @@ type MsgClient interface { UpdateParams(ctx context.Context, in *MsgUpdateParams, opts ...grpc.CallOption) (*MsgUpdateParamsResponse, error) // NonAtomicExec allows users to submit multiple messages for non-atomic execution. NonAtomicExec(ctx context.Context, in *MsgNonAtomicExec, opts ...grpc.CallOption) (*MsgNonAtomicExecResponse, error) + // MigrateAccount migrates the account to x/accounts. + MigrateAccount(ctx context.Context, in *MsgMigrateAccount, opts ...grpc.CallOption) (*MsgMigrateAccountResponse, error) } type msgClient struct { @@ -373,6 +494,15 @@ func (c *msgClient) NonAtomicExec(ctx context.Context, in *MsgNonAtomicExec, opt return out, nil } +func (c *msgClient) MigrateAccount(ctx context.Context, in *MsgMigrateAccount, opts ...grpc.CallOption) (*MsgMigrateAccountResponse, error) { + out := new(MsgMigrateAccountResponse) + err := c.cc.Invoke(ctx, "/cosmos.auth.v1beta1.Msg/MigrateAccount", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // MsgServer is the server API for Msg service. type MsgServer interface { // UpdateParams defines a (governance) operation for updating the x/auth module @@ -380,6 +510,8 @@ type MsgServer interface { UpdateParams(context.Context, *MsgUpdateParams) (*MsgUpdateParamsResponse, error) // NonAtomicExec allows users to submit multiple messages for non-atomic execution. NonAtomicExec(context.Context, *MsgNonAtomicExec) (*MsgNonAtomicExecResponse, error) + // MigrateAccount migrates the account to x/accounts. + MigrateAccount(context.Context, *MsgMigrateAccount) (*MsgMigrateAccountResponse, error) } // UnimplementedMsgServer can be embedded to have forward compatible implementations. @@ -392,6 +524,9 @@ func (*UnimplementedMsgServer) UpdateParams(ctx context.Context, req *MsgUpdateP func (*UnimplementedMsgServer) NonAtomicExec(ctx context.Context, req *MsgNonAtomicExec) (*MsgNonAtomicExecResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method NonAtomicExec not implemented") } +func (*UnimplementedMsgServer) MigrateAccount(ctx context.Context, req *MsgMigrateAccount) (*MsgMigrateAccountResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method MigrateAccount not implemented") +} func RegisterMsgServer(s grpc1.Server, srv MsgServer) { s.RegisterService(&_Msg_serviceDesc, srv) @@ -433,6 +568,24 @@ func _Msg_NonAtomicExec_Handler(srv interface{}, ctx context.Context, dec func(i return interceptor(ctx, in, info, handler) } +func _Msg_MigrateAccount_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgMigrateAccount) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).MigrateAccount(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cosmos.auth.v1beta1.Msg/MigrateAccount", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).MigrateAccount(ctx, req.(*MsgMigrateAccount)) + } + return interceptor(ctx, in, info, handler) +} + var Msg_serviceDesc = _Msg_serviceDesc var _Msg_serviceDesc = grpc.ServiceDesc{ ServiceName: "cosmos.auth.v1beta1.Msg", @@ -446,6 +599,10 @@ var _Msg_serviceDesc = grpc.ServiceDesc{ MethodName: "NonAtomicExec", Handler: _Msg_NonAtomicExec_Handler, }, + { + MethodName: "MigrateAccount", + Handler: _Msg_MigrateAccount_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "cosmos/auth/v1beta1/tx.proto", @@ -637,6 +794,90 @@ func (m *MsgNonAtomicExecResponse) MarshalToSizedBuffer(dAtA []byte) (int, error return len(dAtA) - i, nil } +func (m *MsgMigrateAccount) 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 *MsgMigrateAccount) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgMigrateAccount) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.AccountInitMsg != nil { + { + size, err := m.AccountInitMsg.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTx(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + if len(m.AccountType) > 0 { + i -= len(m.AccountType) + copy(dAtA[i:], m.AccountType) + i = encodeVarintTx(dAtA, i, uint64(len(m.AccountType))) + i-- + dAtA[i] = 0x12 + } + if len(m.Signer) > 0 { + i -= len(m.Signer) + copy(dAtA[i:], m.Signer) + i = encodeVarintTx(dAtA, i, uint64(len(m.Signer))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MsgMigrateAccountResponse) 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 *MsgMigrateAccountResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgMigrateAccountResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.InitResponse != nil { + { + size, err := m.InitResponse.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTx(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + func encodeVarintTx(dAtA []byte, offset int, v uint64) int { offset -= sovTx(v) base := offset @@ -723,6 +964,40 @@ func (m *MsgNonAtomicExecResponse) Size() (n int) { return n } +func (m *MsgMigrateAccount) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Signer) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.AccountType) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + if m.AccountInitMsg != nil { + l = m.AccountInitMsg.Size() + n += 1 + l + sovTx(uint64(l)) + } + return n +} + +func (m *MsgMigrateAccountResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.InitResponse != nil { + l = m.InitResponse.Size() + n += 1 + l + sovTx(uint64(l)) + } + return n +} + func sovTx(x uint64) (n int) { return (math_bits.Len64(x|1) + 6) / 7 } @@ -1212,6 +1487,242 @@ func (m *MsgNonAtomicExecResponse) Unmarshal(dAtA []byte) error { } return nil } +func (m *MsgMigrateAccount) 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 ErrIntOverflowTx + } + 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: MsgMigrateAccount: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgMigrateAccount: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Signer", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Signer = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AccountType", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.AccountType = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AccountInitMsg", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.AccountInitMsg == nil { + m.AccountInitMsg = &any.Any{} + } + if err := m.AccountInitMsg.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgMigrateAccountResponse) 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 ErrIntOverflowTx + } + 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: MsgMigrateAccountResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgMigrateAccountResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field InitResponse", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.InitResponse == nil { + m.InitResponse = &any.Any{} + } + if err := m.InitResponse.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func skipTx(dAtA []byte) (n int, err error) { l := len(dAtA) iNdEx := 0 diff --git a/x/auth/vesting/testutil/expected_keepers_mocks.go b/x/auth/vesting/testutil/expected_keepers_mocks.go index 7612d81e200b..1df8f8ebbf2b 100644 --- a/x/auth/vesting/testutil/expected_keepers_mocks.go +++ b/x/auth/vesting/testutil/expected_keepers_mocks.go @@ -8,7 +8,6 @@ import ( context "context" reflect "reflect" - transaction "cosmossdk.io/core/transaction" types "github.com/cosmos/cosmos-sdk/types" gomock "github.com/golang/mock/gomock" ) @@ -82,84 +81,3 @@ func (mr *MockBankKeeperMockRecorder) SendCoins(ctx, fromAddr, toAddr, amt inter mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendCoins", reflect.TypeOf((*MockBankKeeper)(nil).SendCoins), ctx, fromAddr, toAddr, amt) } - -// MockAccountsModKeeper is a mock of AccountsModKeeper interface. -type MockAccountsModKeeper struct { - ctrl *gomock.Controller - recorder *MockAccountsModKeeperMockRecorder -} - -// MockAccountsModKeeperMockRecorder is the mock recorder for MockAccountsModKeeper. -type MockAccountsModKeeperMockRecorder struct { - mock *MockAccountsModKeeper -} - -// NewMockAccountsModKeeper creates a new mock instance. -func NewMockAccountsModKeeper(ctrl *gomock.Controller) *MockAccountsModKeeper { - mock := &MockAccountsModKeeper{ctrl: ctrl} - mock.recorder = &MockAccountsModKeeperMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockAccountsModKeeper) EXPECT() *MockAccountsModKeeperMockRecorder { - return m.recorder -} - -// InitAccountNumberSeqUnsafe mocks base method. -func (m *MockAccountsModKeeper) InitAccountNumberSeqUnsafe(ctx context.Context, currentAccNum uint64) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "InitAccountNumberSeqUnsafe", ctx, currentAccNum) - ret0, _ := ret[0].(error) - return ret0 -} - -// InitAccountNumberSeqUnsafe indicates an expected call of InitAccountNumberSeqUnsafe. -func (mr *MockAccountsModKeeperMockRecorder) InitAccountNumberSeqUnsafe(ctx, currentAccNum interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "InitAccountNumberSeqUnsafe", reflect.TypeOf((*MockAccountsModKeeper)(nil).InitAccountNumberSeqUnsafe), ctx, currentAccNum) -} - -// IsAccountsModuleAccount mocks base method. -func (m *MockAccountsModKeeper) IsAccountsModuleAccount(ctx context.Context, accountAddr []byte) bool { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "IsAccountsModuleAccount", ctx, accountAddr) - ret0, _ := ret[0].(bool) - return ret0 -} - -// IsAccountsModuleAccount indicates an expected call of IsAccountsModuleAccount. -func (mr *MockAccountsModKeeperMockRecorder) IsAccountsModuleAccount(ctx, accountAddr interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsAccountsModuleAccount", reflect.TypeOf((*MockAccountsModKeeper)(nil).IsAccountsModuleAccount), ctx, accountAddr) -} - -// NextAccountNumber mocks base method. -func (m *MockAccountsModKeeper) NextAccountNumber(ctx context.Context) (uint64, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "NextAccountNumber", ctx) - ret0, _ := ret[0].(uint64) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// NextAccountNumber indicates an expected call of NextAccountNumber. -func (mr *MockAccountsModKeeperMockRecorder) NextAccountNumber(ctx interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NextAccountNumber", reflect.TypeOf((*MockAccountsModKeeper)(nil).NextAccountNumber), ctx) -} - -// SendModuleMessage mocks base method. -func (m *MockAccountsModKeeper) SendModuleMessage(ctx context.Context, sender []byte, msg transaction.Msg) (transaction.Msg, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "SendModuleMessage", ctx, sender, msg) - ret0, _ := ret[0].(transaction.Msg) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// SendModuleMessage indicates an expected call of SendModuleMessage. -func (mr *MockAccountsModKeeperMockRecorder) SendModuleMessage(ctx, sender, msg interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendModuleMessage", reflect.TypeOf((*MockAccountsModKeeper)(nil).SendModuleMessage), ctx, sender, msg) -} diff --git a/x/auth/vesting/types/expected_keepers.go b/x/auth/vesting/types/expected_keepers.go index 3d8815385d10..6c4feaf4d20c 100644 --- a/x/auth/vesting/types/expected_keepers.go +++ b/x/auth/vesting/types/expected_keepers.go @@ -4,7 +4,6 @@ import ( "context" sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/x/auth/types" ) // BankKeeper defines the expected interface contract the vesting module requires @@ -14,7 +13,3 @@ type BankKeeper interface { SendCoins(ctx context.Context, fromAddr, toAddr sdk.AccAddress, amt sdk.Coins) error BlockedAddr(addr sdk.AccAddress) bool } - -type AccountsModKeeper interface { - types.AccountsModKeeper -} diff --git a/x/auth/vesting/types/period.go b/x/auth/vesting/types/period.go index 174bd3437a1e..f9c31a2601c4 100644 --- a/x/auth/vesting/types/period.go +++ b/x/auth/vesting/types/period.go @@ -42,7 +42,7 @@ func (p Periods) TotalAmount() sdk.Coins { // String implements the fmt.Stringer interface func (p Periods) String() string { - periodsListString := make([]string, len(p)) + periodsListString := make([]string, 0, len(p)) for _, period := range p { periodsListString = append(periodsListString, period.String()) } diff --git a/x/auth/vesting/types/period_test.go b/x/auth/vesting/types/period_test.go new file mode 100644 index 000000000000..636e6255a0d0 --- /dev/null +++ b/x/auth/vesting/types/period_test.go @@ -0,0 +1,49 @@ +package types_test + +import ( + "testing" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/auth/vesting/types" +) + +func TestPeriodsString(t *testing.T) { + tests := []struct { + name string + periods types.Periods + want string + }{ + { + "empty slice", + nil, + "Vesting Periods:", + }, + { + "1 period", + types.Periods{ + {Length: int64(12 * 60 * 60), Amount: sdk.Coins{sdk.NewInt64Coin("feeatom", 500), sdk.NewInt64Coin("statom", 50)}}, + }, + "Vesting Periods:\n\t\t" + `length:43200 amount: amount:`, + }, + { + "many", + types.Periods{ + {Length: int64(12 * 60 * 60), Amount: sdk.Coins{sdk.NewInt64Coin(feeDenom, 500), sdk.NewInt64Coin(stakeDenom, 50)}}, + {Length: int64(6 * 60 * 60), Amount: sdk.Coins{sdk.NewInt64Coin(feeDenom, 250), sdk.NewInt64Coin(stakeDenom, 25)}}, + {Length: int64(6 * 60 * 60), Amount: sdk.Coins{sdk.NewInt64Coin(feeDenom, 100), sdk.NewInt64Coin(stakeDenom, 15)}}, + }, + "Vesting Periods:\n\t\t" + `length:43200 amount: amount: , ` + + `length:21600 amount: amount: , ` + + `length:21600 amount: amount:`, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := tt.periods.String() + if got != tt.want { + t.Fatalf("Mismatch in values:\n\tGot: %q\n\tWant: %q", got, tt.want) + } + }) + } +} diff --git a/x/auth/vesting/types/vesting.pb.go b/x/auth/vesting/types/vesting.pb.go index c5c2a54a8295..86bedb042b1c 100644 --- a/x/auth/vesting/types/vesting.pb.go +++ b/x/auth/vesting/types/vesting.pb.go @@ -4,11 +4,11 @@ package types import ( - types "github.com/cosmos/cosmos-sdk/x/auth/types" fmt "fmt" github_com_cosmos_cosmos_sdk_types "github.com/cosmos/cosmos-sdk/types" types1 "github.com/cosmos/cosmos-sdk/types" _ "github.com/cosmos/cosmos-sdk/types/tx/amino" + types "github.com/cosmos/cosmos-sdk/x/auth/types" _ "github.com/cosmos/gogoproto/gogoproto" proto "github.com/cosmos/gogoproto/proto" io "io" diff --git a/x/auth/vesting/types/vesting_account_test.go b/x/auth/vesting/types/vesting_account_test.go index 54330978d127..f4d3aa044456 100644 --- a/x/auth/vesting/types/vesting_account_test.go +++ b/x/auth/vesting/types/vesting_account_test.go @@ -21,9 +21,9 @@ import ( moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil" authcodec "github.com/cosmos/cosmos-sdk/x/auth/codec" "github.com/cosmos/cosmos-sdk/x/auth/keeper" + authtestutil "github.com/cosmos/cosmos-sdk/x/auth/testutil" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" "github.com/cosmos/cosmos-sdk/x/auth/vesting" - vestingtestutil "github.com/cosmos/cosmos-sdk/x/auth/vesting/testutil" "github.com/cosmos/cosmos-sdk/x/auth/vesting/types" ) @@ -50,7 +50,6 @@ func (s *VestingAccountTestSuite) SetupTest() { // gomock initializations ctrl := gomock.NewController(&testing.T{}) - acctsModKeeper := vestingtestutil.NewMockAccountsModKeeper(ctrl) maccPerms := map[string][]string{ "fee_collector": nil, @@ -65,7 +64,7 @@ func (s *VestingAccountTestSuite) SetupTest() { env, encCfg.Codec, authtypes.ProtoBaseAccount, - acctsModKeeper, + authtestutil.NewMockAccountsModKeeper(ctrl), maccPerms, authcodec.NewBech32Codec("cosmos"), "cosmos", @@ -917,8 +916,6 @@ func TestGenesisAccountValidate(t *testing.T) { } for _, tt := range tests { - tt := tt - t.Run(tt.name, func(t *testing.T) { require.Equal(t, tt.expErr, tt.acc.Validate() != nil) }) diff --git a/x/authz/CHANGELOG.md b/x/authz/CHANGELOG.md index 6d3a4ccb1ea2..a898236bcdb1 100644 --- a/x/authz/CHANGELOG.md +++ b/x/authz/CHANGELOG.md @@ -37,6 +37,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### API Breaking Changes +* [#21632](https://github.com/cosmos/cosmos-sdk/pull/21632) `NewKeeper` now takes `address.Codec` instead of `authKeeper`. * [#21044](https://github.com/cosmos/cosmos-sdk/pull/21044) `k.DispatchActions` returns a slice of byte slices of proto marshaled anys instead of a slice of byte slices of `sdk.Result.Data`. * [#20502](https://github.com/cosmos/cosmos-sdk/pull/20502) `Accept` on the `Authorization` interface now expects the authz environment in the `context.Context`. This is already done when `Accept` is called by `k.DispatchActions`, but should be done manually if `Accept` is called directly. * [#19783](https://github.com/cosmos/cosmos-sdk/pull/19783) Removes the use of Accounts String() method diff --git a/x/authz/README.md b/x/authz/README.md index c4752c2eddc6..405bd5427e6a 100644 --- a/x/authz/README.md +++ b/x/authz/README.md @@ -38,12 +38,12 @@ The `x/authz` module defines interfaces and messages grant authorizations to per on behalf of one account to other accounts. The design is defined in the [ADR 030](https://github.com/cosmos/cosmos-sdk/blob/main/docs/architecture/adr-030-authz-module.md). A *grant* is an allowance to execute a Msg by the grantee on behalf of the granter. -Authorization is an interface that must be implemented by a concrete authorization logic to validate and execute grants. Authorizations are extensible and can be defined for any Msg service method even outside of the module where the Msg method is defined. See the `SendAuthorization` example in the next section for more details. +Authorization is an interface that must be implemented by a concrete authorization logic to validate and execute grants. Authorizations are extensible and can be defined for any Msg service method, even if the Msg method is defined outside of the module. See the `SendAuthorization` example in the next section for more details. -**Note:** The authz module is different from the [auth (authentication)](../modules/auth/) module that is responsible for specifying the base transaction and account types. +**Note:** The authz module is different from the [auth (authentication)](../modules/auth/) module, which is responsible for specifying the base transaction and account types. ```go reference -https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/x/authz/authorizations.go#L11-L25 +https://github.com/cosmos/cosmos-sdk/blob/v0.52.0-beta.1/x/authz/authorizations.go#L14-L28 ``` ### Built-in Authorizations @@ -55,11 +55,11 @@ The Cosmos SDK `x/authz` module comes with following authorization types: `GenericAuthorization` implements the `Authorization` interface that gives unrestricted permission to execute the provided Msg on behalf of granter's account. ```protobuf reference -https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/authz/v1beta1/authz.proto#L14-L22 +https://github.com/cosmos/cosmos-sdk/blob/v0.52.0-beta.1/x/authz/proto/cosmos/authz/v1beta1/authz.proto#L14-L22 ``` ```go reference -https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/x/authz/generic_authorization.go#L16-L29 +https://github.com/cosmos/cosmos-sdk/blob/v0.52.0-beta.1/x/authz/generic_authorization.go#L18-L34 ``` * `msg` stores Msg type URL. @@ -72,11 +72,11 @@ https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/x/authz/generic_authorizat * It takes an (optional) `AllowList` that specifies to which addresses a grantee can send token. ```protobuf reference -https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/bank/v1beta1/authz.proto#L11-L30 +https://github.com/cosmos/cosmos-sdk/blob/v0.52.0-beta.1/x/bank/proto/cosmos/bank/v1beta1/authz.proto#L11-L29 ``` ```go reference -https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/x/bank/types/send_authorization.go#L29-L62 +https://github.com/cosmos/cosmos-sdk/blob/v0.52.0-beta.1/x/bank/types/send_authorization.go#L33-L73 ``` * `spend_limit` keeps track of how many coins are left in the authorization. @@ -84,21 +84,21 @@ https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/x/bank/types/send_authoriz #### StakeAuthorization -`StakeAuthorization` implements the `Authorization` interface for messages in the [staking module](https://docs.cosmos.network/main/build/modules/staking). It takes an `AuthorizationType` to specify whether you want to authorise delegating, undelegating or redelegating (i.e. these have to be authorised separately). It also takes an optional `MaxTokens` that keeps track of a limit to the amount of tokens that can be delegated/undelegated/redelegated. If left empty, the amount is unlimited. Additionally, this Msg takes an `AllowList` or a `DenyList`, which allows you to select which validators you allow or deny grantees to stake with. +`StakeAuthorization` implements the `Authorization` interface for messages in the [staking module](https://docs.cosmos.network/main/build/modules/staking). It takes an `AuthorizationType` to specify whether you want to authorize delegation, undelegation, redelegation or cancel unbonding delegation, each of which must be authorized separately. It also takes an optional `MaxTokens` that keeps track of a limit to the amount of tokens that can be delegated/undelegated/redelegated. If left empty, the amount is unlimited. Additionally, this Msg takes an `AllowList` or a `DenyList`, enabling you to specify which validators the grantee can or cannot stake with. ```protobuf reference -https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/staking/v1beta1/authz.proto#L11-L35 +https://github.com/cosmos/cosmos-sdk/blob/v0.52.0-beta.1/x/staking/proto/cosmos/staking/v1beta1/authz.proto#L11-L34 ``` ```go reference -https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/x/staking/types/authz.go#L15-L35 +https://github.com/cosmos/cosmos-sdk/blob/v0.52.0-beta.1/x/staking/types/authz.go#L78-L166 ``` ### Gas -In order to prevent DoS attacks, granting `StakeAuthorization`s with `x/authz` incurs gas. `StakeAuthorization` allows you to authorize another account to delegate, undelegate, or redelegate to validators. The authorizer can define a list of validators they allow or deny delegations to. The Cosmos SDK iterates over these lists and charge 10 gas for each validator in both of the lists. +To prevent DoS attacks, granting `StakeAuthorization`s with `x/authz` incurs gas. `StakeAuthorization` allows you to authorize another account to delegate, undelegate, or redelegate tokens to validators. The granter can define a list of validators for which they allow or deny delegations. The Cosmos SDK then iterates over these lists and charge 10 gas for each validator included in both lists. -Since the state maintaining a list for granter, grantee pair with same expiration, we are iterating over the list to remove the grant (in case of any revoke of particular `msgType`) from the list and we are charging 20 gas per iteration. +Since the state maintains a list of granter-grantee pairs with same expiration, we iterate over this list to remove the grant from the list (in case of any revoke of particular `msgType`), charging 20 gas for each iteration. ## State @@ -111,17 +111,17 @@ Grants are identified by combining granter address (the address bytes of the gra The grant object encapsulates an `Authorization` type and an expiration timestamp: ```protobuf reference -https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/authz/v1beta1/authz.proto#L24-L32 +https://github.com/cosmos/cosmos-sdk/blob/v0.52.0-beta.1/x/authz/proto/cosmos/authz/v1beta1/authz.proto#L24-L32 ``` ### GrantQueue We are maintaining a queue for authz pruning. Whenever a grant is created, an item will be added to `GrantQueue` with a key of expiration, granter, grantee. -In `EndBlock` (which runs for every block) we continuously check and prune the expired grants by forming a prefix key with current blocktime that passed the stored expiration in `GrantQueue`, we iterate through all the matched records from `GrantQueue` and delete them from the `GrantQueue` & `Grant`s store. +In `EndBlock` (which runs for every block) we continuously check and prune the expired grants by forming a prefix key with current blocktime that passed the stored expiration in `GrantQueue`, we iterate through all the matched records from `GrantQueue` and delete maximum of 200 grants from the `GrantQueue` & `Grant`s store for each run. ```go reference -https://github.com/cosmos/cosmos-sdk/blob/5f4ddc6f80f9707320eec42182184207fff3833a/x/authz/keeper/keeper.go#L378-L403 +https://github.com/cosmos/cosmos-sdk/blob/v0.52.0-beta.1/x/authz/keeper/keeper.go#L479-L520 ``` * GrantQueue: `0x02 | expiration_bytes | granter_address_len (1 byte) | granter_address_bytes | grantee_address_len (1 byte) | grantee_address_bytes -> ProtocolBuffer(GrantQueueItem)` @@ -129,7 +129,7 @@ https://github.com/cosmos/cosmos-sdk/blob/5f4ddc6f80f9707320eec42182184207fff383 The `expiration_bytes` are the expiration date in UTC with the format `"2006-01-02T15:04:05.000000000"`. ```go reference -https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/x/authz/keeper/keys.go#L77-L93 +https://github.com/cosmos/cosmos-sdk/blob/v0.52.0-beta.1/x/authz/keeper/keys.go#L84-L100 ``` The `GrantQueueItem` object contains the list of type urls between granter and grantee that expire at the time indicated in the key. @@ -146,7 +146,7 @@ If there is already a grant for the `(granter, grantee, Authorization)` triple, An authorization grant for authz `MsgGrant` is not allowed and will return an error. This is for preventing user from accidentally authorizing their entire account to a different account. ```protobuf reference -https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/authz/v1beta1/tx.proto#L35-L45 +https://github.com/cosmos/cosmos-sdk/blob/v0.52.0-beta.1/x/authz/proto/cosmos/authz/v1beta1/tx.proto#L45-L55 ``` The message handling should fail if: @@ -161,7 +161,7 @@ The message handling should fail if: A grant can be removed with the `MsgRevoke` message. ```protobuf reference -https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/authz/v1beta1/tx.proto#L69-L78 +https://github.com/cosmos/cosmos-sdk/blob/v0.52.0-beta.1/x/authz/proto/cosmos/authz/v1beta1/tx.proto#L79-L88 ``` The message handling should fail if: @@ -176,7 +176,7 @@ NOTE: The `MsgExec` message removes a grant if the grant has expired. The `MsgRevokeAll` message revokes all grants issued by the specified granter. This is useful for quickly removing all authorizations granted by a single granter without specifying individual message types or grantees. ```protobuf reference -https://github.com/cosmos/cosmos-sdk/tree/main/x/authz/proto/cosmos/authz/v1beta1/tx.proto#L93-L100 +https://github.com/cosmos/cosmos-sdk/blob/v0.52.0-beta.1/x/authz/proto/cosmos/authz/v1beta1/tx.proto#L93-L100 ``` The message handling should fail if: @@ -189,7 +189,7 @@ The message handling should fail if: When a grantee wants to execute a transaction on behalf of a granter, they must send `MsgExec`. ```protobuf reference -https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/authz/v1beta1/tx.proto#L52-L63 +https://github.com/cosmos/cosmos-sdk/blob/v0.52.0-beta.1/x/authz/proto/cosmos/authz/v1beta1/tx.proto#L60-L72 ``` The message handling should fail if: @@ -314,6 +314,20 @@ Example: simd tx authz revoke cosmos1.. /cosmos.bank.v1beta1.MsgSend --from=cosmos1.. ``` +##### revoke-all + +The `revoke-all` command allows a granter to revoke all authorizations created by the granter. + +```bash +simd tx authz revoke-all --from=[granter] [flags] +``` + +Example: + +```bash +simd tx authz revoke-all --from=cosmos1.. +``` + ### gRPC A user can query the `authz` module using gRPC endpoints. @@ -335,27 +349,6 @@ grpcurl -plaintext \ cosmos.authz.v1beta1.Query/Grants ``` -Example Output: - -```bash -{ - "grants": [ - { - "authorization": { - "@type": "/cosmos.bank.v1beta1.SendAuthorization", - "spendLimit": [ - { - "denom":"stake", - "amount":"100" - } - ] - }, - "expiration": "2022-01-01T00:00:00Z" - } - ] -} -``` - ### REST A user can query the `authz` module using REST endpoints. @@ -369,25 +362,3 @@ Example: ```bash curl "localhost:1317/cosmos/authz/v1beta1/grants?granter=cosmos1..&grantee=cosmos1..&msg_type_url=/cosmos.bank.v1beta1.MsgSend" ``` - -Example Output: - -```bash -{ - "grants": [ - { - "authorization": { - "@type": "/cosmos.bank.v1beta1.SendAuthorization", - "spend_limit": [ - { - "denom": "stake", - "amount": "100" - } - ] - }, - "expiration": "2022-01-01T00:00:00Z" - } - ], - "pagination": null -} -``` diff --git a/x/authz/authorization_grant_test.go b/x/authz/authorization_grant_test.go index 76d50f6c2dfc..7b048d3f2413 100644 --- a/x/authz/authorization_grant_test.go +++ b/x/authz/authorization_grant_test.go @@ -35,7 +35,6 @@ func TestNewGrant(t *testing.T) { } for _, tc := range tcs { - tc := tc t.Run(tc.title, func(t *testing.T) { _, err := NewGrant(tc.blockTime, tc.a, tc.expire) expecError(require.New(t), tc.err, err) @@ -59,7 +58,6 @@ func TestValidateBasic(t *testing.T) { } for _, tc := range tcs { - tc := tc t.Run(tc.title, func(t *testing.T) { grant := Grant{ Authorization: tc.authorization, diff --git a/x/authz/expected_keepers.go b/x/authz/expected_keepers.go index fad3b4b74467..b2ee6bd16fbf 100644 --- a/x/authz/expected_keepers.go +++ b/x/authz/expected_keepers.go @@ -3,18 +3,9 @@ package authz import ( "context" - "cosmossdk.io/core/address" - sdk "github.com/cosmos/cosmos-sdk/types" ) -// AccountKeeper defines the expected account keeper (noalias) -type AccountKeeper interface { - AddressCodec() address.Codec - GetAccount(ctx context.Context, addr sdk.AccAddress) sdk.AccountI - NewAccountWithAddress(ctx context.Context, addr sdk.AccAddress) sdk.AccountI -} - // BankKeeper defines the expected interface needed to retrieve account balances. type BankKeeper interface { SpendableCoins(ctx context.Context, addr sdk.AccAddress) sdk.Coins diff --git a/x/authz/go.mod b/x/authz/go.mod index 6438c2e98c00..a40b44423b98 100644 --- a/x/authz/go.mod +++ b/x/authz/go.mod @@ -3,8 +3,8 @@ module cosmossdk.io/x/authz go 1.23.1 require ( - cosmossdk.io/api v0.7.5 - cosmossdk.io/core v1.0.0-alpha.2 + cosmossdk.io/api v0.7.6 + cosmossdk.io/core v1.0.0-alpha.4 cosmossdk.io/depinject v1.0.0 cosmossdk.io/errors v1.0.1 cosmossdk.io/log v1.4.1 @@ -21,8 +21,8 @@ require ( github.com/grpc-ecosystem/grpc-gateway v1.16.0 github.com/spf13/cobra v1.8.1 github.com/stretchr/testify v1.9.0 - google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 - google.golang.org/grpc v1.66.2 + google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 + google.golang.org/grpc v1.67.1 google.golang.org/protobuf v1.34.2 ) @@ -30,7 +30,7 @@ require ( buf.build/gen/go/cometbft/cometbft/protocolbuffers/go v1.34.2-20240701160653-fedbb9acfd2f.2 // indirect buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.34.2-20240130113600-88ef6483f90f.2 // indirect cosmossdk.io/collections v0.4.0 // indirect - cosmossdk.io/schema v0.2.0 // indirect + cosmossdk.io/schema v0.3.1-0.20240930054013-7c6e0388a3f9 // indirect filippo.io/edwards25519 v1.1.0 // indirect github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect github.com/99designs/keyring v1.2.2 // indirect @@ -50,7 +50,6 @@ require ( github.com/cometbft/cometbft-db v0.15.0 // indirect github.com/cometbft/cometbft/api v1.0.0-rc.1 // indirect github.com/cosmos/btcutil v1.0.5 // indirect - github.com/cosmos/cosmos-db v1.0.3-0.20240911104526-ddc3f09bfc22 // indirect github.com/cosmos/crypto v0.1.2 // indirect github.com/cosmos/go-bip39 v1.0.0 // indirect github.com/cosmos/gogogateway v1.2.0 // indirect @@ -95,7 +94,7 @@ require ( github.com/hashicorp/hcl v1.0.0 // indirect github.com/hashicorp/yamux v0.1.1 // indirect github.com/hdevalence/ed25519consensus v0.2.0 // indirect - github.com/huandu/skiplist v1.2.0 // indirect + github.com/huandu/skiplist v1.2.1 // indirect github.com/iancoleman/strcase v0.3.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jmhodges/levigo v1.0.0 // indirect @@ -118,9 +117,9 @@ require ( github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/client_golang v1.20.3 // indirect + github.com/prometheus/client_golang v1.20.4 // indirect github.com/prometheus/client_model v0.6.1 // indirect - github.com/prometheus/common v0.59.1 // indirect + github.com/prometheus/common v0.60.0 // indirect github.com/prometheus/procfs v0.15.1 // indirect github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect github.com/rogpeppe/go-internal v1.12.0 // indirect @@ -156,7 +155,7 @@ require ( golang.org/x/text v0.18.0 // indirect golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect gotest.tools/v3 v3.5.1 // indirect @@ -164,10 +163,11 @@ require ( sigs.k8s.io/yaml v1.4.0 // indirect ) -require cosmossdk.io/core/testing v0.0.0-00010101000000-000000000000 +require cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29 require ( github.com/cockroachdb/fifo v0.0.0-20240606204812-0bbfbd93a7ce // indirect + github.com/cosmos/cosmos-db v1.0.3-0.20240911104526-ddc3f09bfc22 // indirect github.com/google/uuid v1.6.0 // indirect ) @@ -177,7 +177,6 @@ replace github.com/cosmos/cosmos-sdk => ../../. replace ( cosmossdk.io/api => ../../api cosmossdk.io/collections => ../../collections - cosmossdk.io/core/testing => ../../core/testing cosmossdk.io/store => ../../store cosmossdk.io/x/bank => ../bank cosmossdk.io/x/staking => ../staking diff --git a/x/authz/go.sum b/x/authz/go.sum index cd6b45de5cf6..7588b565a0d7 100644 --- a/x/authz/go.sum +++ b/x/authz/go.sum @@ -4,8 +4,10 @@ buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.34.2-20240130113600-88e buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.34.2-20240130113600-88ef6483f90f.2/go.mod h1:HqcXMSa5qnNuakaMUo+hWhF51mKbcrZxGl9Vp5EeJXc= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cosmossdk.io/core v1.0.0-alpha.2 h1:epU0Xwces4Rgl5bMhHHkXGaGDcyucNGlC/JDH+Suckg= -cosmossdk.io/core v1.0.0-alpha.2/go.mod h1:abgLjeFLhtuKIYZWSPlVUgQBrKObO7ULV35KYfexE90= +cosmossdk.io/core v1.0.0-alpha.4 h1:9iuroT9ejDYETCsGkzkvs/wAY/5UFl7nCIINFRxyMJY= +cosmossdk.io/core v1.0.0-alpha.4/go.mod h1:3u9cWq1FAVtiiCrDPpo4LhR+9V6k/ycSG4/Y/tREWCY= +cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29 h1:NxxUo0GMJUbIuVg0R70e3cbn9eFTEuMr7ev1AFvypdY= +cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29/go.mod h1:8s2tPeJtSiQuoyPmr2Ag7meikonISO4Fv4MoO8+ORrs= cosmossdk.io/depinject v1.0.0 h1:dQaTu6+O6askNXO06+jyeUAnF2/ssKwrrszP9t5q050= cosmossdk.io/depinject v1.0.0/go.mod h1:zxK/h3HgHoA/eJVtiSsoaRaRA2D5U4cJ5thIG4ssbB8= cosmossdk.io/errors v1.0.1 h1:bzu+Kcr0kS/1DuPBtUFdWjzLqyUuCiyHjyJB6srBV/0= @@ -14,8 +16,8 @@ cosmossdk.io/log v1.4.1 h1:wKdjfDRbDyZRuWa8M+9nuvpVYxrEOwbD/CA8hvhU8QM= cosmossdk.io/log v1.4.1/go.mod h1:k08v0Pyq+gCP6phvdI6RCGhLf/r425UT6Rk/m+o74rU= cosmossdk.io/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE= cosmossdk.io/math v1.3.0/go.mod h1:vnRTxewy+M7BtXBNFybkuhSH4WfedVAAnERHgVFhp3k= -cosmossdk.io/schema v0.2.0 h1:UH5CR1DqUq8yP+5Np8PbvG4YX0zAUsTN2Qk6yThmfMk= -cosmossdk.io/schema v0.2.0/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= +cosmossdk.io/schema v0.3.1-0.20240930054013-7c6e0388a3f9 h1:DmOoS/1PeY6Ih0hAVlJ69kLMUrLV+TCbfICrZtB1vdU= +cosmossdk.io/schema v0.3.1-0.20240930054013-7c6e0388a3f9/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMbk2FiG/kXiLl8BRyzTWDw7gX/Hz7Dd5eDMs= @@ -290,8 +292,8 @@ github.com/hdevalence/ed25519consensus v0.2.0/go.mod h1:w3BHWjwJbFU29IRHL1Iqkw3s github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/huandu/go-assert v1.1.5 h1:fjemmA7sSfYHJD7CUqs9qTwwfdNAx7/j2/ZlHXzNB3c= github.com/huandu/go-assert v1.1.5/go.mod h1:yOLvuqZwmcHIC5rIzrBhT7D3Q9c3GFnd0JrPVhn/06U= -github.com/huandu/skiplist v1.2.0 h1:gox56QD77HzSC0w+Ws3MH3iie755GBJU1OER3h5VsYw= -github.com/huandu/skiplist v1.2.0/go.mod h1:7v3iFjLcSAzO4fN5B8dvebvo/qsfumiLiDXMrPiHF9w= +github.com/huandu/skiplist v1.2.1 h1:dTi93MgjwErA/8idWTzIw4Y1kZsMWx35fmI2c8Rij7w= +github.com/huandu/skiplist v1.2.1/go.mod h1:7v3iFjLcSAzO4fN5B8dvebvo/qsfumiLiDXMrPiHF9w= github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI= github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= @@ -400,8 +402,8 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= -github.com/prometheus/client_golang v1.20.3 h1:oPksm4K8B+Vt35tUhw6GbSNSgVlVSBH0qELP/7u83l4= -github.com/prometheus/client_golang v1.20.3/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_golang v1.20.4 h1:Tgh3Yr67PaOv/uTqloMsCEdeuFTatm5zIq5+qNN23vI= +github.com/prometheus/client_golang v1.20.4/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -410,8 +412,8 @@ github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= -github.com/prometheus/common v0.59.1 h1:LXb1quJHWm1P6wq/U824uxYi4Sg0oGvNeUm1z5dJoX0= -github.com/prometheus/common v0.59.1/go.mod h1:GpWM7dewqmVYcd7SmRaiWVe9SSqjf0UrwnYnpEZNuT0= +github.com/prometheus/common v0.60.0 h1:+V9PAREWNvJMAuJ1x1BaWl9dewMW4YrHZQbx0sJNllA= +github.com/prometheus/common v0.60.0/go.mod h1:h0LYf1R1deLSKtD4Vdg8gy4RuOvENW2J/h19V5NADQw= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/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= @@ -634,10 +636,10 @@ google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEY google.golang.org/genproto v0.0.0-20220314164441-57ef72a4c106/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E= google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de h1:F6qOa9AZTYJXOUEr4jDysRDLrm4PHePlge4v4TGAlxY= google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:VUhTRKeHn9wwcdrk73nvdC9gF178Tzhmt/qyaFcPLSo= -google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 h1:+rdxYoE3E5htTEWIe15GlN6IfvbURM//Jt0mmkmm6ZU= -google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117/go.mod h1:OimBR/bc1wPO9iV4NC2bpyjy3VnAwZh5EBPQdtaE5oo= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:pPJltXNxVzT4pK9yD8vR9X75DaWYYmLGMsEvBfFQZzQ= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= +google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 h1:wKguEg1hsxI2/L3hUYrpo1RVi48K+uTyzKqprwLXsb8= +google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142/go.mod h1:d6be+8HhtEtucleCbxpPW9PA9XwISACu8nvpPqF0BVo= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f h1:cUMEy+8oS78BWIH9OWazBkzbr090Od9tWBNtZHkOhf0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= @@ -648,8 +650,8 @@ google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= -google.golang.org/grpc v1.66.2 h1:3QdXkuq3Bkh7w+ywLdLvM56cmGvQHUMZpiCzt6Rqaoo= -google.golang.org/grpc v1.66.2/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y= +google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E= +google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= 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= diff --git a/x/authz/keeper/genesis.go b/x/authz/keeper/genesis.go index c669f2aa2622..45762713b61d 100644 --- a/x/authz/keeper/genesis.go +++ b/x/authz/keeper/genesis.go @@ -18,11 +18,11 @@ func (k Keeper) InitGenesis(ctx context.Context, data *authz.GenesisState) error continue } - grantee, err := k.authKeeper.AddressCodec().StringToBytes(entry.Grantee) + grantee, err := k.addrCdc.StringToBytes(entry.Grantee) if err != nil { return err } - granter, err := k.authKeeper.AddressCodec().StringToBytes(entry.Granter) + granter, err := k.addrCdc.StringToBytes(entry.Granter) if err != nil { return err } @@ -44,11 +44,11 @@ func (k Keeper) InitGenesis(ctx context.Context, data *authz.GenesisState) error func (k Keeper) ExportGenesis(ctx context.Context) (*authz.GenesisState, error) { var entries []authz.GrantAuthorization err := k.IterateGrants(ctx, func(granter, grantee sdk.AccAddress, grant authz.Grant) (bool, error) { - granterAddr, err := k.authKeeper.AddressCodec().BytesToString(granter) + granterAddr, err := k.addrCdc.BytesToString(granter) if err != nil { return false, err } - granteeAddr, err := k.authKeeper.AddressCodec().BytesToString(grantee) + granteeAddr, err := k.addrCdc.BytesToString(grantee) if err != nil { return false, err } diff --git a/x/authz/keeper/genesis_test.go b/x/authz/keeper/genesis_test.go index 6cc9db972025..53b96a8f94be 100644 --- a/x/authz/keeper/genesis_test.go +++ b/x/authz/keeper/genesis_test.go @@ -4,7 +4,6 @@ import ( "testing" "time" - "github.com/golang/mock/gomock" "github.com/stretchr/testify/suite" "cosmossdk.io/core/header" @@ -14,11 +13,10 @@ import ( storetypes "cosmossdk.io/store/types" "cosmossdk.io/x/authz/keeper" authzmodule "cosmossdk.io/x/authz/module" - authztestutil "cosmossdk.io/x/authz/testutil" bank "cosmossdk.io/x/bank/types" "github.com/cosmos/cosmos-sdk/baseapp" - "github.com/cosmos/cosmos-sdk/codec/address" + addresscodec "github.com/cosmos/cosmos-sdk/codec/address" codectestutil "github.com/cosmos/cosmos-sdk/codec/testutil" "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" "github.com/cosmos/cosmos-sdk/runtime" @@ -37,11 +35,10 @@ var ( type GenesisTestSuite struct { suite.Suite - ctx sdk.Context - keeper keeper.Keeper - baseApp *baseapp.BaseApp - accountKeeper *authztestutil.MockAccountKeeper - encCfg moduletestutil.TestEncodingConfig + ctx sdk.Context + keeper keeper.Keeper + baseApp *baseapp.BaseApp + encCfg moduletestutil.TestEncodingConfig } func (suite *GenesisTestSuite) SetupTest() { @@ -52,11 +49,6 @@ func (suite *GenesisTestSuite) SetupTest() { suite.encCfg = moduletestutil.MakeTestEncodingConfig(codectestutil.CodecOptions{}, authzmodule.AppModule{}) - // gomock initializations - ctrl := gomock.NewController(suite.T()) - suite.accountKeeper = authztestutil.NewMockAccountKeeper(ctrl) - suite.accountKeeper.EXPECT().AddressCodec().Return(address.NewBech32Codec("cosmos")).AnyTimes() - suite.baseApp = baseapp.NewBaseApp( "authz", log.NewNopLogger(), @@ -71,7 +63,8 @@ func (suite *GenesisTestSuite) SetupTest() { msr.SetInterfaceRegistry(suite.encCfg.InterfaceRegistry) env := runtime.NewEnvironment(storeService, coretesting.NewNopLogger(), runtime.EnvWithMsgRouterService(msr)) - suite.keeper = keeper.NewKeeper(env, suite.encCfg.Codec, suite.accountKeeper) + addrCdc := addresscodec.NewBech32Codec("cosmos") + suite.keeper = keeper.NewKeeper(env, suite.encCfg.Codec, addrCdc) } func (suite *GenesisTestSuite) TestImportExportGenesis() { diff --git a/x/authz/keeper/grpc_query.go b/x/authz/keeper/grpc_query.go index 89cb8ac67d65..f3bba8f1aed6 100644 --- a/x/authz/keeper/grpc_query.go +++ b/x/authz/keeper/grpc_query.go @@ -25,12 +25,12 @@ func (k Keeper) Grants(ctx context.Context, req *authz.QueryGrantsRequest) (*aut return nil, status.Errorf(codes.InvalidArgument, "empty request") } - granter, err := k.authKeeper.AddressCodec().StringToBytes(req.Granter) + granter, err := k.addrCdc.StringToBytes(req.Granter) if err != nil { return nil, err } - grantee, err := k.authKeeper.AddressCodec().StringToBytes(req.Grantee) + grantee, err := k.addrCdc.StringToBytes(req.Grantee) if err != nil { return nil, err } @@ -95,7 +95,7 @@ func (k Keeper) GranterGrants(ctx context.Context, req *authz.QueryGranterGrants return nil, status.Errorf(codes.InvalidArgument, "empty request") } - granter, err := k.authKeeper.AddressCodec().StringToBytes(req.Granter) + granter, err := k.addrCdc.StringToBytes(req.Granter) if err != nil { return nil, err } @@ -116,7 +116,7 @@ func (k Keeper) GranterGrants(ctx context.Context, req *authz.QueryGranterGrants grantee := firstAddressFromGrantStoreKey(key) - granteeAddr, err := k.authKeeper.AddressCodec().BytesToString(grantee) + granteeAddr, err := k.addrCdc.BytesToString(grantee) if err != nil { return nil, err } @@ -146,7 +146,7 @@ func (k Keeper) GranteeGrants(ctx context.Context, req *authz.QueryGranteeGrants return nil, status.Errorf(codes.InvalidArgument, "empty request") } - grantee, err := k.authKeeper.AddressCodec().StringToBytes(req.Grantee) + grantee, err := k.addrCdc.StringToBytes(req.Grantee) if err != nil { return nil, err } @@ -169,7 +169,7 @@ func (k Keeper) GranteeGrants(ctx context.Context, req *authz.QueryGranteeGrants return nil, status.Error(codes.Internal, err.Error()) } - granterAddr, err := k.authKeeper.AddressCodec().BytesToString(granter) + granterAddr, err := k.addrCdc.BytesToString(granter) if err != nil { return nil, err } diff --git a/x/authz/keeper/grpc_query_test.go b/x/authz/keeper/grpc_query_test.go index 6cb51dbae0f7..d4239b0f854c 100644 --- a/x/authz/keeper/grpc_query_test.go +++ b/x/authz/keeper/grpc_query_test.go @@ -21,9 +21,9 @@ func (suite *TestSuite) TestGRPCQueryAuthorization() { expAuthorization authz.Authorization ) - addr0, err := suite.accountKeeper.AddressCodec().BytesToString(addrs[0]) + addr0, err := suite.addrCdc.BytesToString(addrs[0]) suite.Require().NoError(err) - addr1, err := suite.accountKeeper.AddressCodec().BytesToString(addrs[1]) + addr1, err := suite.addrCdc.BytesToString(addrs[1]) suite.Require().NoError(err) testCases := []struct { @@ -137,7 +137,7 @@ func (suite *TestSuite) TestGRPCQueryGranterGrants() { require := suite.Require() queryClient, addrs := suite.queryClient, suite.addrs - addr0, err := suite.accountKeeper.AddressCodec().BytesToString(addrs[0]) + addr0, err := suite.addrCdc.BytesToString(addrs[0]) suite.Require().NoError(err) testCases := []struct { @@ -192,7 +192,6 @@ func (suite *TestSuite) TestGRPCQueryGranterGrants() { } for _, tc := range testCases { - tc := tc suite.Run(fmt.Sprintf("Case %s", tc.msg), func() { tc.preRun() result, err := queryClient.GranterGrants(gocontext.Background(), &tc.request) @@ -210,9 +209,9 @@ func (suite *TestSuite) TestGRPCQueryGranteeGrants() { require := suite.Require() queryClient, addrs := suite.queryClient, suite.addrs - addr0, err := suite.accountKeeper.AddressCodec().BytesToString(addrs[0]) + addr0, err := suite.addrCdc.BytesToString(addrs[0]) suite.Require().NoError(err) - addr2, err := suite.accountKeeper.AddressCodec().BytesToString(addrs[2]) + addr2, err := suite.addrCdc.BytesToString(addrs[2]) suite.Require().NoError(err) testCases := []struct { @@ -275,8 +274,6 @@ func (suite *TestSuite) TestGRPCQueryGranteeGrants() { } for _, tc := range testCases { - tc := tc - suite.Run(fmt.Sprintf("Case %s", tc.msg), func() { tc.preRun() result, err := queryClient.GranteeGrants(gocontext.Background(), &tc.request) @@ -302,7 +299,7 @@ func (suite *TestSuite) createSendAuthorization(grantee, granter sdk.AccAddress) func (suite *TestSuite) createSendAuthorizationWithAllowList(grantee, granter sdk.AccAddress) authz.Authorization { exp := suite.ctx.HeaderInfo().Time.Add(time.Hour) newCoins := sdk.NewCoins(sdk.NewInt64Coin("steak", 100)) - addr, err := suite.accountKeeper.AddressCodec().BytesToString(suite.addrs[5]) + addr, err := suite.addrCdc.BytesToString(suite.addrs[5]) suite.Require().NoError(err) authorization := &banktypes.SendAuthorization{SpendLimit: newCoins, AllowList: []string{addr}} err = suite.authzKeeper.SaveGrant(suite.ctx, grantee, granter, authorization, &exp) diff --git a/x/authz/keeper/keeper.go b/x/authz/keeper/keeper.go index ecfed97ee7cf..087f73aafcf3 100644 --- a/x/authz/keeper/keeper.go +++ b/x/authz/keeper/keeper.go @@ -9,6 +9,7 @@ import ( gogoproto "github.com/cosmos/gogoproto/proto" gogoprotoany "github.com/cosmos/gogoproto/types/any" + "cosmossdk.io/core/address" "cosmossdk.io/core/appmodule" corecontext "cosmossdk.io/core/context" errorsmod "cosmossdk.io/errors" @@ -30,16 +31,16 @@ const gasCostPerIteration = uint64(20) type Keeper struct { appmodule.Environment - cdc codec.Codec - authKeeper authz.AccountKeeper + cdc codec.Codec + addrCdc address.Codec } // NewKeeper constructs a message authorization Keeper -func NewKeeper(env appmodule.Environment, cdc codec.Codec, ak authz.AccountKeeper) Keeper { +func NewKeeper(env appmodule.Environment, cdc codec.Codec, addrCdc address.Codec) Keeper { return Keeper{ Environment: env, cdc: cdc, - authKeeper: ak, + addrCdc: addrCdc, } } @@ -206,11 +207,11 @@ func (k Keeper) SaveGrant(ctx context.Context, grantee, granter sdk.AccAddress, return err } - granterAddr, err := k.authKeeper.AddressCodec().BytesToString(granter) + granterAddr, err := k.addrCdc.BytesToString(granter) if err != nil { return err } - granteeAddr, err := k.authKeeper.AddressCodec().BytesToString(grantee) + granteeAddr, err := k.addrCdc.BytesToString(grantee) if err != nil { return err } @@ -229,12 +230,12 @@ func (k Keeper) DeleteGrant(ctx context.Context, grantee, granter sdk.AccAddress skey := grantStoreKey(grantee, granter, msgType) grant, found := k.getGrant(ctx, skey) if !found { - granterAddr, err := k.authKeeper.AddressCodec().BytesToString(granter) + granterAddr, err := k.addrCdc.BytesToString(granter) if err != nil { return errorsmod.Wrapf(authz.ErrNoAuthorizationFound, "could not convert granter address to string") } - granteeAddr, err := k.authKeeper.AddressCodec().BytesToString(grantee) + granteeAddr, err := k.addrCdc.BytesToString(grantee) if err != nil { return errorsmod.Wrapf(authz.ErrNoAuthorizationFound, "could not convert grantee address to string") @@ -255,11 +256,11 @@ func (k Keeper) DeleteGrant(ctx context.Context, grantee, granter sdk.AccAddress return err } - granterAddr, err := k.authKeeper.AddressCodec().BytesToString(granter) + granterAddr, err := k.addrCdc.BytesToString(granter) if err != nil { return err } - granteeAddr, err := k.authKeeper.AddressCodec().BytesToString(grantee) + granteeAddr, err := k.addrCdc.BytesToString(grantee) if err != nil { return err } @@ -291,7 +292,7 @@ func (k Keeper) DeleteAllGrants(ctx context.Context, granter sdk.AccAddress) err } } - grantAddr, err := k.authKeeper.AddressCodec().BytesToString(granter) + grantAddr, err := k.addrCdc.BytesToString(granter) if err != nil { return err } diff --git a/x/authz/keeper/keeper_test.go b/x/authz/keeper/keeper_test.go index dcfd710fc264..f977ffef22fb 100644 --- a/x/authz/keeper/keeper_test.go +++ b/x/authz/keeper/keeper_test.go @@ -9,6 +9,7 @@ import ( "github.com/golang/mock/gomock" "github.com/stretchr/testify/suite" + "cosmossdk.io/core/address" "cosmossdk.io/core/header" coretesting "cosmossdk.io/core/testing" "cosmossdk.io/log" @@ -20,7 +21,7 @@ import ( banktypes "cosmossdk.io/x/bank/types" "github.com/cosmos/cosmos-sdk/baseapp" - "github.com/cosmos/cosmos-sdk/codec/address" + addresscodec "github.com/cosmos/cosmos-sdk/codec/address" codectestutil "github.com/cosmos/cosmos-sdk/codec/testutil" "github.com/cosmos/cosmos-sdk/runtime" "github.com/cosmos/cosmos-sdk/testutil" @@ -39,15 +40,15 @@ var ( type TestSuite struct { suite.Suite - ctx sdk.Context - addrs []sdk.AccAddress - authzKeeper authzkeeper.Keeper - accountKeeper *authztestutil.MockAccountKeeper - bankKeeper *authztestutil.MockBankKeeper - baseApp *baseapp.BaseApp - encCfg moduletestutil.TestEncodingConfig - queryClient authz.QueryClient - msgSrvr authz.MsgServer + ctx sdk.Context + addrs []sdk.AccAddress + authzKeeper authzkeeper.Keeper + bankKeeper *authztestutil.MockBankKeeper + baseApp *baseapp.BaseApp + encCfg moduletestutil.TestEncodingConfig + queryClient authz.QueryClient + msgSrvr authz.MsgServer + addrCdc address.Codec } func (s *TestSuite) SetupTest() { @@ -70,16 +71,13 @@ func (s *TestSuite) SetupTest() { // gomock initializations ctrl := gomock.NewController(s.T()) - s.accountKeeper = authztestutil.NewMockAccountKeeper(ctrl) - - s.accountKeeper.EXPECT().AddressCodec().Return(address.NewBech32Codec("cosmos")).AnyTimes() - s.bankKeeper = authztestutil.NewMockBankKeeper(ctrl) banktypes.RegisterInterfaces(s.encCfg.InterfaceRegistry) banktypes.RegisterMsgServer(s.baseApp.MsgServiceRouter(), s.bankKeeper) env := runtime.NewEnvironment(storeService, coretesting.NewNopLogger(), runtime.EnvWithQueryRouterService(s.baseApp.GRPCQueryRouter()), runtime.EnvWithMsgRouterService(s.baseApp.MsgServiceRouter())) - s.authzKeeper = authzkeeper.NewKeeper(env, s.encCfg.Codec, s.accountKeeper) + s.addrCdc = addresscodec.NewBech32Codec("cosmos") + s.authzKeeper = authzkeeper.NewKeeper(env, s.encCfg.Codec, s.addrCdc) queryHelper := baseapp.NewQueryServerTestHelper(s.ctx, s.encCfg.InterfaceRegistry) authz.RegisterQueryServer(queryHelper, s.authzKeeper) @@ -183,7 +181,7 @@ func (s *TestSuite) TestKeeperIter() { granteeAddr := addrs[1] granter2Addr := addrs[2] e := ctx.HeaderInfo().Time.AddDate(1, 0, 0) - sendAuthz := banktypes.NewSendAuthorization(coins100, nil, s.accountKeeper.AddressCodec()) + sendAuthz := banktypes.NewSendAuthorization(coins100, nil, s.addrCdc) err := s.authzKeeper.SaveGrant(ctx, granteeAddr, granterAddr, sendAuthz, &e) s.Require().NoError(err) @@ -207,7 +205,7 @@ func (s *TestSuite) TestKeeperGranterGrantsIter() { grantee2Addr := addrs[3] grantee3Addr := addrs[4] e := ctx.HeaderInfo().Time.AddDate(1, 0, 0) - sendAuthz := banktypes.NewSendAuthorization(coins100, nil, s.accountKeeper.AddressCodec()) + sendAuthz := banktypes.NewSendAuthorization(coins100, nil, s.addrCdc) err := s.authzKeeper.SaveGrant(ctx, granteeAddr, granterAddr, sendAuthz, &e) s.Require().NoError(err) @@ -238,13 +236,13 @@ func (s *TestSuite) TestDispatchAction() { granterAddr := addrs[0] granteeAddr := addrs[1] - granterStrAddr, err := s.accountKeeper.AddressCodec().BytesToString(addrs[0]) + granterStrAddr, err := s.addrCdc.BytesToString(addrs[0]) s.Require().NoError(err) - granteeStrAddr, err := s.accountKeeper.AddressCodec().BytesToString(addrs[1]) + granteeStrAddr, err := s.addrCdc.BytesToString(addrs[1]) s.Require().NoError(err) - recipientStrAddr, err := s.accountKeeper.AddressCodec().BytesToString(addrs[2]) + recipientStrAddr, err := s.addrCdc.BytesToString(addrs[2]) s.Require().NoError(err) - a := banktypes.NewSendAuthorization(coins100, nil, s.accountKeeper.AddressCodec()) + a := banktypes.NewSendAuthorization(coins100, nil, s.addrCdc) testCases := []struct { name string @@ -402,11 +400,11 @@ func (s *TestSuite) TestDispatchedEvents() { addrs := s.addrs granterAddr := addrs[0] granteeAddr := addrs[1] - granterStrAddr, err := s.accountKeeper.AddressCodec().BytesToString(addrs[0]) + granterStrAddr, err := s.addrCdc.BytesToString(addrs[0]) s.Require().NoError(err) - granteeStrAddr, err := s.accountKeeper.AddressCodec().BytesToString(addrs[1]) + granteeStrAddr, err := s.addrCdc.BytesToString(addrs[1]) s.Require().NoError(err) - recipientStrAddr, err := s.accountKeeper.AddressCodec().BytesToString(addrs[2]) + recipientStrAddr, err := s.addrCdc.BytesToString(addrs[2]) s.Require().NoError(err) expiration := s.ctx.HeaderInfo().Time.Add(1 * time.Second) // must be in the future @@ -505,7 +503,7 @@ func (s *TestSuite) TestGetAuthorization() { genAuthMulti := authz.NewGenericAuthorization(sdk.MsgTypeURL(&banktypes.MsgMultiSend{})) genAuthSend := authz.NewGenericAuthorization(sdk.MsgTypeURL(&banktypes.MsgSend{})) - sendAuth := banktypes.NewSendAuthorization(coins10, nil, s.accountKeeper.AddressCodec()) + sendAuth := banktypes.NewSendAuthorization(coins10, nil, s.addrCdc) start := s.ctx.HeaderInfo().Time expired := start.Add(time.Duration(1) * time.Second) diff --git a/x/authz/keeper/msg_server.go b/x/authz/keeper/msg_server.go index 1722a4f0bb14..ecacf6e50521 100644 --- a/x/authz/keeper/msg_server.go +++ b/x/authz/keeper/msg_server.go @@ -20,12 +20,12 @@ func (k Keeper) Grant(ctx context.Context, msg *authz.MsgGrant) (*authz.MsgGrant return nil, authz.ErrGranteeIsGranter } - grantee, err := k.authKeeper.AddressCodec().StringToBytes(msg.Grantee) + grantee, err := k.addrCdc.StringToBytes(msg.Grantee) if err != nil { return nil, sdkerrors.ErrInvalidAddress.Wrapf("invalid grantee address: %s", err) } - granter, err := k.authKeeper.AddressCodec().StringToBytes(msg.Granter) + granter, err := k.addrCdc.StringToBytes(msg.Granter) if err != nil { return nil, sdkerrors.ErrInvalidAddress.Wrapf("invalid granter address: %s", err) } @@ -64,12 +64,12 @@ func (k Keeper) Revoke(ctx context.Context, msg *authz.MsgRevoke) (*authz.MsgRev return nil, authz.ErrGranteeIsGranter } - grantee, err := k.authKeeper.AddressCodec().StringToBytes(msg.Grantee) + grantee, err := k.addrCdc.StringToBytes(msg.Grantee) if err != nil { return nil, sdkerrors.ErrInvalidAddress.Wrapf("invalid grantee address: %s", err) } - granter, err := k.authKeeper.AddressCodec().StringToBytes(msg.Granter) + granter, err := k.addrCdc.StringToBytes(msg.Granter) if err != nil { return nil, sdkerrors.ErrInvalidAddress.Wrapf("invalid granter address: %s", err) } @@ -87,7 +87,7 @@ func (k Keeper) Revoke(ctx context.Context, msg *authz.MsgRevoke) (*authz.MsgRev // RevokeAll implements the MsgServer.RevokeAll method. func (k Keeper) RevokeAll(ctx context.Context, msg *authz.MsgRevokeAll) (*authz.MsgRevokeAllResponse, error) { - granter, err := k.authKeeper.AddressCodec().StringToBytes(msg.Granter) + granter, err := k.addrCdc.StringToBytes(msg.Granter) if err != nil { return nil, sdkerrors.ErrInvalidAddress.Wrapf("invalid granter address: %s", err) } @@ -105,7 +105,7 @@ func (k Keeper) Exec(ctx context.Context, msg *authz.MsgExec) (*authz.MsgExecRes return nil, errors.New("empty address string is not allowed") } - grantee, err := k.authKeeper.AddressCodec().StringToBytes(msg.Grantee) + grantee, err := k.addrCdc.StringToBytes(msg.Grantee) if err != nil { return nil, sdkerrors.ErrInvalidAddress.Wrapf("invalid grantee address: %s", err) } diff --git a/x/authz/keeper/msg_server_test.go b/x/authz/keeper/msg_server_test.go index 2958e45a9915..fe19fb4247da 100644 --- a/x/authz/keeper/msg_server_test.go +++ b/x/authz/keeper/msg_server_test.go @@ -3,23 +3,17 @@ package keeper_test import ( "time" - "github.com/golang/mock/gomock" - "cosmossdk.io/core/header" sdkmath "cosmossdk.io/math" "cosmossdk.io/x/authz" banktypes "cosmossdk.io/x/bank/types" - "github.com/cosmos/cosmos-sdk/codec/address" simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" sdk "github.com/cosmos/cosmos-sdk/types" - authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" ) func (suite *TestSuite) createAccounts() []sdk.AccAddress { addrs := simtestutil.CreateIncrementalAccounts(2) - suite.accountKeeper.EXPECT().GetAccount(gomock.Any(), suite.addrs[0]).Return(authtypes.NewBaseAccountWithAddress(suite.addrs[0])).AnyTimes() - suite.accountKeeper.EXPECT().GetAccount(gomock.Any(), suite.addrs[1]).Return(authtypes.NewBaseAccountWithAddress(suite.addrs[1])).AnyTimes() return addrs } @@ -28,17 +22,15 @@ func (suite *TestSuite) TestGrant() { addrs := suite.createAccounts() curBlockTime := ctx.HeaderInfo().Time - suite.accountKeeper.EXPECT().AddressCodec().Return(address.NewBech32Codec("cosmos")).AnyTimes() - oneHour := curBlockTime.Add(time.Hour) oneYear := curBlockTime.AddDate(1, 0, 0) coins := sdk.NewCoins(sdk.NewCoin("steak", sdkmath.NewInt(10))) grantee, granter := addrs[0], addrs[1] - granterStrAddr, err := suite.accountKeeper.AddressCodec().BytesToString(granter) + granterStrAddr, err := suite.addrCdc.BytesToString(granter) suite.Require().NoError(err) - granteeStrAddr, err := suite.accountKeeper.AddressCodec().BytesToString(grantee) + granteeStrAddr, err := suite.addrCdc.BytesToString(grantee) suite.Require().NoError(err) testCases := []struct { @@ -50,7 +42,7 @@ func (suite *TestSuite) TestGrant() { { name: "identical grantee and granter", malleate: func() *authz.MsgGrant { - grant, err := authz.NewGrant(curBlockTime, banktypes.NewSendAuthorization(coins, nil, suite.accountKeeper.AddressCodec()), &oneYear) + grant, err := authz.NewGrant(curBlockTime, banktypes.NewSendAuthorization(coins, nil, suite.addrCdc), &oneYear) suite.Require().NoError(err) return &authz.MsgGrant{ Granter: granteeStrAddr, @@ -64,7 +56,7 @@ func (suite *TestSuite) TestGrant() { { name: "invalid granter", malleate: func() *authz.MsgGrant { - grant, err := authz.NewGrant(curBlockTime, banktypes.NewSendAuthorization(coins, nil, suite.accountKeeper.AddressCodec()), &oneYear) + grant, err := authz.NewGrant(curBlockTime, banktypes.NewSendAuthorization(coins, nil, suite.addrCdc), &oneYear) suite.Require().NoError(err) return &authz.MsgGrant{ Granter: "invalid", @@ -78,7 +70,7 @@ func (suite *TestSuite) TestGrant() { { name: "invalid grantee", malleate: func() *authz.MsgGrant { - grant, err := authz.NewGrant(curBlockTime, banktypes.NewSendAuthorization(coins, nil, suite.accountKeeper.AddressCodec()), &oneYear) + grant, err := authz.NewGrant(curBlockTime, banktypes.NewSendAuthorization(coins, nil, suite.addrCdc), &oneYear) suite.Require().NoError(err) return &authz.MsgGrant{ Granter: granterStrAddr, @@ -107,7 +99,7 @@ func (suite *TestSuite) TestGrant() { name: "invalid grant, past time", malleate: func() *authz.MsgGrant { pTime := curBlockTime.Add(-time.Hour) - grant, err := authz.NewGrant(curBlockTime, banktypes.NewSendAuthorization(coins, nil, suite.accountKeeper.AddressCodec()), &oneHour) // we only need the authorization + grant, err := authz.NewGrant(curBlockTime, banktypes.NewSendAuthorization(coins, nil, suite.addrCdc), &oneHour) // we only need the authorization suite.Require().NoError(err) return &authz.MsgGrant{ Granter: granterStrAddr, @@ -125,14 +117,10 @@ func (suite *TestSuite) TestGrant() { name: "grantee account does not exist on chain: valid grant", malleate: func() *authz.MsgGrant { newAcc := sdk.AccAddress("valid") - suite.accountKeeper.EXPECT().GetAccount(gomock.Any(), newAcc).Return(nil).AnyTimes() - acc := authtypes.NewBaseAccountWithAddress(newAcc) - suite.accountKeeper.EXPECT().NewAccountWithAddress(gomock.Any(), newAcc).Return(acc).AnyTimes() - - grant, err := authz.NewGrant(curBlockTime, banktypes.NewSendAuthorization(coins, nil, suite.accountKeeper.AddressCodec()), &oneYear) + grant, err := authz.NewGrant(curBlockTime, banktypes.NewSendAuthorization(coins, nil, suite.addrCdc), &oneYear) suite.Require().NoError(err) - addr, err := suite.accountKeeper.AddressCodec().BytesToString(newAcc) + addr, err := suite.addrCdc.BytesToString(newAcc) suite.Require().NoError(err) return &authz.MsgGrant{ @@ -145,7 +133,7 @@ func (suite *TestSuite) TestGrant() { { name: "valid grant", malleate: func() *authz.MsgGrant { - grant, err := authz.NewGrant(curBlockTime, banktypes.NewSendAuthorization(coins, nil, suite.accountKeeper.AddressCodec()), &oneYear) + grant, err := authz.NewGrant(curBlockTime, banktypes.NewSendAuthorization(coins, nil, suite.addrCdc), &oneYear) suite.Require().NoError(err) return &authz.MsgGrant{ Granter: granterStrAddr, @@ -157,7 +145,7 @@ func (suite *TestSuite) TestGrant() { { name: "valid grant, same grantee, granter pair but different msgType", malleate: func() *authz.MsgGrant { - g, err := authz.NewGrant(curBlockTime, banktypes.NewSendAuthorization(coins, nil, suite.accountKeeper.AddressCodec()), &oneHour) + g, err := authz.NewGrant(curBlockTime, banktypes.NewSendAuthorization(coins, nil, suite.addrCdc), &oneHour) suite.Require().NoError(err) _, err = suite.msgSrvr.Grant(suite.ctx, &authz.MsgGrant{ Granter: granterStrAddr, @@ -178,7 +166,7 @@ func (suite *TestSuite) TestGrant() { { name: "valid grant with allow list", malleate: func() *authz.MsgGrant { - grant, err := authz.NewGrant(curBlockTime, banktypes.NewSendAuthorization(coins, []sdk.AccAddress{granter}, suite.accountKeeper.AddressCodec()), &oneYear) + grant, err := authz.NewGrant(curBlockTime, banktypes.NewSendAuthorization(coins, []sdk.AccAddress{granter}, suite.addrCdc), &oneYear) suite.Require().NoError(err) return &authz.MsgGrant{ Granter: granterStrAddr, @@ -190,7 +178,7 @@ func (suite *TestSuite) TestGrant() { { name: "valid grant with nil expiration time", malleate: func() *authz.MsgGrant { - grant, err := authz.NewGrant(curBlockTime, banktypes.NewSendAuthorization(coins, nil, suite.accountKeeper.AddressCodec()), nil) + grant, err := authz.NewGrant(curBlockTime, banktypes.NewSendAuthorization(coins, nil, suite.addrCdc), nil) suite.Require().NoError(err) return &authz.MsgGrant{ Granter: granterStrAddr, @@ -232,9 +220,9 @@ func (suite *TestSuite) TestRevoke() { addrs := suite.createAccounts() grantee, granter := addrs[0], addrs[1] - granterStrAddr, err := suite.accountKeeper.AddressCodec().BytesToString(granter) + granterStrAddr, err := suite.addrCdc.BytesToString(granter) suite.Require().NoError(err) - granteeStrAddr, err := suite.accountKeeper.AddressCodec().BytesToString(grantee) + granteeStrAddr, err := suite.addrCdc.BytesToString(grantee) suite.Require().NoError(err) testCases := []struct { @@ -334,9 +322,9 @@ func (suite *TestSuite) TestExec() { addrs := suite.createAccounts() grantee, granter := addrs[0], addrs[1] - granterStrAddr, err := suite.accountKeeper.AddressCodec().BytesToString(granter) + granterStrAddr, err := suite.addrCdc.BytesToString(granter) suite.Require().NoError(err) - granteeStrAddr, err := suite.accountKeeper.AddressCodec().BytesToString(grantee) + granteeStrAddr, err := suite.addrCdc.BytesToString(grantee) suite.Require().NoError(err) coins := sdk.NewCoins(sdk.NewCoin("steak", sdkmath.NewInt(10))) @@ -402,15 +390,15 @@ func (suite *TestSuite) TestExec() { func (suite *TestSuite) TestPruneExpiredGrants() { addrs := suite.createAccounts() - addr0, err := suite.accountKeeper.AddressCodec().BytesToString(addrs[0]) + addr0, err := suite.addrCdc.BytesToString(addrs[0]) suite.Require().NoError(err) - addr1, err := suite.accountKeeper.AddressCodec().BytesToString(addrs[1]) + addr1, err := suite.addrCdc.BytesToString(addrs[1]) suite.Require().NoError(err) timeNow := suite.ctx.BlockTime() expiration := timeNow.Add(time.Hour) coins := sdk.NewCoins(sdk.NewCoin("steak", sdkmath.NewInt(10))) - grant, err := authz.NewGrant(timeNow, banktypes.NewSendAuthorization(coins, nil, suite.accountKeeper.AddressCodec()), &expiration) + grant, err := authz.NewGrant(timeNow, banktypes.NewSendAuthorization(coins, nil, suite.addrCdc), &expiration) suite.Require().NoError(err) _, err = suite.msgSrvr.Grant(suite.ctx, &authz.MsgGrant{ @@ -454,7 +442,7 @@ func (suite *TestSuite) TestRevokeAllGrants() { addrs := simtestutil.CreateIncrementalAccounts(3) grantee, grantee2, granter := addrs[0], addrs[1], addrs[2] - granterStrAddr, err := suite.accountKeeper.AddressCodec().BytesToString(granter) + granterStrAddr, err := suite.addrCdc.BytesToString(granter) suite.Require().NoError(err) testCases := []struct { diff --git a/x/authz/module/abci_test.go b/x/authz/module/abci_test.go index 58811ba6294e..4696a1194ee9 100644 --- a/x/authz/module/abci_test.go +++ b/x/authz/module/abci_test.go @@ -4,7 +4,6 @@ import ( "testing" "time" - "github.com/golang/mock/gomock" "github.com/stretchr/testify/require" "cosmossdk.io/core/header" @@ -14,7 +13,6 @@ import ( "cosmossdk.io/x/authz" "cosmossdk.io/x/authz/keeper" authzmodule "cosmossdk.io/x/authz/module" - authztestutil "cosmossdk.io/x/authz/testutil" banktypes "cosmossdk.io/x/bank/types" "github.com/cosmos/cosmos-sdk/baseapp" @@ -25,7 +23,6 @@ import ( simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" sdk "github.com/cosmos/cosmos-sdk/types" moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil" - authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" ) func TestExpiredGrantsQueue(t *testing.T) { @@ -57,22 +54,13 @@ func TestExpiredGrantsQueue(t *testing.T) { smallCoins := sdk.NewCoins(sdk.NewInt64Coin("stake", 10)) sendAuthz := banktypes.NewSendAuthorization(smallCoins, nil, codectestutil.CodecOptions{}.GetAddressCodec()) - ctrl := gomock.NewController(t) - accountKeeper := authztestutil.NewMockAccountKeeper(ctrl) - accountKeeper.EXPECT().GetAccount(gomock.Any(), granter).Return(authtypes.NewBaseAccountWithAddress(granter)).AnyTimes() - accountKeeper.EXPECT().GetAccount(gomock.Any(), grantee1).Return(authtypes.NewBaseAccountWithAddress(grantee1)).AnyTimes() - accountKeeper.EXPECT().GetAccount(gomock.Any(), grantee2).Return(authtypes.NewBaseAccountWithAddress(grantee2)).AnyTimes() - accountKeeper.EXPECT().GetAccount(gomock.Any(), grantee3).Return(authtypes.NewBaseAccountWithAddress(grantee3)).AnyTimes() - accountKeeper.EXPECT().GetAccount(gomock.Any(), grantee4).Return(authtypes.NewBaseAccountWithAddress(grantee4)).AnyTimes() - - accountKeeper.EXPECT().AddressCodec().Return(address.NewBech32Codec("cosmos")).AnyTimes() - + addrCdc := address.NewBech32Codec("cosmos") env := runtime.NewEnvironment(storeService, coretesting.NewNopLogger(), runtime.EnvWithQueryRouterService(baseApp.GRPCQueryRouter()), runtime.EnvWithMsgRouterService(baseApp.MsgServiceRouter())) - authzKeeper := keeper.NewKeeper(env, encCfg.Codec, accountKeeper) + authzKeeper := keeper.NewKeeper(env, encCfg.Codec, addrCdc) save := func(grantee sdk.AccAddress, exp *time.Time) { err := authzKeeper.SaveGrant(ctx, grantee, granter, sendAuthz, exp) - addr, _ := accountKeeper.AddressCodec().BytesToString(grantee) + addr, _ := addrCdc.BytesToString(grantee) require.NoError(t, err, "Grant from %s", addr) } save(grantee1, &expiration) @@ -88,7 +76,7 @@ func TestExpiredGrantsQueue(t *testing.T) { err := authzmodule.BeginBlocker(ctx, authzKeeper) require.NoError(t, err) - addr, err := accountKeeper.AddressCodec().BytesToString(granter) + addr, err := addrCdc.BytesToString(granter) require.NoError(t, err) res, err := queryClient.GranterGrants(ctx.Context(), &authz.QueryGranterGrantsRequest{ Granter: addr, diff --git a/x/authz/module/depinject.go b/x/authz/module/depinject.go index 849471f8fa27..4a9368053c93 100644 --- a/x/authz/module/depinject.go +++ b/x/authz/module/depinject.go @@ -2,10 +2,10 @@ package module import ( modulev1 "cosmossdk.io/api/cosmos/authz/module/v1" + "cosmossdk.io/core/address" "cosmossdk.io/core/appmodule" "cosmossdk.io/depinject" "cosmossdk.io/depinject/appconfig" - "cosmossdk.io/x/authz" "cosmossdk.io/x/authz/keeper" "github.com/cosmos/cosmos-sdk/codec" @@ -27,11 +27,10 @@ func init() { type ModuleInputs struct { depinject.In - Cdc codec.Codec - AccountKeeper authz.AccountKeeper - BankKeeper authz.BankKeeper - Registry cdctypes.InterfaceRegistry - Environment appmodule.Environment + Cdc codec.Codec + AddressCodec address.Codec + Registry cdctypes.InterfaceRegistry + Environment appmodule.Environment } type ModuleOutputs struct { @@ -42,7 +41,7 @@ type ModuleOutputs struct { } func ProvideModule(in ModuleInputs) ModuleOutputs { - k := keeper.NewKeeper(in.Environment, in.Cdc, in.AccountKeeper) - m := NewAppModule(in.Cdc, k, in.AccountKeeper, in.BankKeeper, in.Registry) + k := keeper.NewKeeper(in.Environment, in.Cdc, in.AddressCodec) + m := NewAppModule(in.Cdc, k, in.Registry) return ModuleOutputs{AuthzKeeper: k, Module: m} } diff --git a/x/authz/module/module.go b/x/authz/module/module.go index 1acb5727b2e8..d25ab35eba88 100644 --- a/x/authz/module/module.go +++ b/x/authz/module/module.go @@ -20,6 +20,7 @@ import ( sdkclient "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/codec" cdctypes "github.com/cosmos/cosmos-sdk/codec/types" + "github.com/cosmos/cosmos-sdk/simsx" "github.com/cosmos/cosmos-sdk/types/module" simtypes "github.com/cosmos/cosmos-sdk/types/simulation" ) @@ -40,27 +41,21 @@ var ( // AppModule implements the sdk.AppModule interface type AppModule struct { - cdc codec.Codec - keeper keeper.Keeper - accountKeeper authz.AccountKeeper - bankKeeper authz.BankKeeper - registry cdctypes.InterfaceRegistry + cdc codec.Codec + keeper keeper.Keeper + registry cdctypes.InterfaceRegistry } // NewAppModule creates a new AppModule object func NewAppModule( cdc codec.Codec, keeper keeper.Keeper, - ak authz.AccountKeeper, - bk authz.BankKeeper, registry cdctypes.InterfaceRegistry, ) AppModule { return AppModule{ - cdc: cdc, - keeper: keeper, - accountKeeper: ak, - bankKeeper: bk, - registry: registry, + cdc: cdc, + keeper: keeper, + registry: registry, } } @@ -166,11 +161,8 @@ func (am AppModule) RegisterStoreDecoder(sdr simtypes.StoreDecoderRegistry) { sdr[keeper.StoreKey] = simulation.NewDecodeStore(am.cdc) } -// WeightedOperations returns the all the gov module operations with their respective weights. -func (am AppModule) WeightedOperations(simState module.SimulationState) []simtypes.WeightedOperation { - return simulation.WeightedOperations( - am.registry, - simState.AppParams, simState.Cdc, simState.TxConfig, - am.accountKeeper, am.bankKeeper, am.keeper, - ) +func (am AppModule) WeightedOperationsX(weights simsx.WeightSource, reg simsx.Registry) { + reg.Add(weights.Get("msg_grant", 100), simulation.MsgGrantFactory()) + reg.Add(weights.Get("msg_revoke", 90), simulation.MsgRevokeFactory(am.keeper)) + reg.Add(weights.Get("msg_exec", 90), simulation.MsgExecFactory(am.keeper)) } diff --git a/x/authz/simulation/decoder_test.go b/x/authz/simulation/decoder_test.go index ff14fd76e316..94f87b729cf4 100644 --- a/x/authz/simulation/decoder_test.go +++ b/x/authz/simulation/decoder_test.go @@ -48,7 +48,6 @@ func TestDecodeStore(t *testing.T) { } for i, tt := range tests { - i, tt := i, tt t.Run(tt.name, func(t *testing.T) { if tt.expectErr { require.Panics(t, func() { dec(kvPairs.Pairs[i], kvPairs.Pairs[i]) }, tt.name) diff --git a/x/authz/simulation/genesis.go b/x/authz/simulation/genesis.go index 59b2d299a46c..de650064407b 100644 --- a/x/authz/simulation/genesis.go +++ b/x/authz/simulation/genesis.go @@ -5,7 +5,6 @@ import ( "time" v1 "cosmossdk.io/api/cosmos/gov/v1" - "cosmossdk.io/core/address" sdkmath "cosmossdk.io/math" "cosmossdk.io/x/authz" banktypes "cosmossdk.io/x/bank/types" @@ -16,23 +15,31 @@ import ( simtypes "github.com/cosmos/cosmos-sdk/types/simulation" ) +// RandomizedGenState generates a random GenesisState for authz. +func RandomizedGenState(simState *module.SimulationState) { + var grants []authz.GrantAuthorization + simState.AppParams.GetOrGenerate("authz", &grants, simState.Rand, func(r *rand.Rand) { + grants = genGrant(r, simState.Accounts, simState.GenTimestamp) + }) + + authzGrantsGenesis := authz.NewGenesisState(grants) + + simState.GenState[authz.ModuleName] = simState.Cdc.MustMarshalJSON(authzGrantsGenesis) +} + // genGrant returns a slice of authorization grants. -func genGrant(r *rand.Rand, accounts []simtypes.Account, genT time.Time, cdc address.Codec) []authz.GrantAuthorization { +func genGrant(r *rand.Rand, accounts []simtypes.Account, genT time.Time) []authz.GrantAuthorization { authorizations := make([]authz.GrantAuthorization, len(accounts)-1) for i := 0; i < len(accounts)-1; i++ { - granter := accounts[i] - grantee := accounts[i+1] var expiration *time.Time if i%3 != 0 { // generate some grants with no expire time e := genT.AddDate(1, 0, 0) expiration = &e } - granterAddr, _ := cdc.BytesToString(granter.Address) - granteeAddr, _ := cdc.BytesToString(grantee.Address) authorizations[i] = authz.GrantAuthorization{ - Granter: granterAddr, - Grantee: granteeAddr, - Authorization: generateRandomGrant(r, cdc), + Granter: accounts[i].AddressBech32, + Grantee: accounts[i+1].AddressBech32, + Authorization: generateRandomGrant(r), Expiration: expiration, } } @@ -40,32 +47,17 @@ func genGrant(r *rand.Rand, accounts []simtypes.Account, genT time.Time, cdc add return authorizations } -func generateRandomGrant(r *rand.Rand, addressCodec address.Codec) *codectypes.Any { - authorizations := make([]*codectypes.Any, 2) - sendAuthz := banktypes.NewSendAuthorization(sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(1000))), nil, addressCodec) - authorizations[0] = newAnyAuthorization(sendAuthz) - authorizations[1] = newAnyAuthorization(authz.NewGenericAuthorization(sdk.MsgTypeURL(&v1.MsgSubmitProposal{}))) - - return authorizations[r.Intn(len(authorizations))] +func generateRandomGrant(r *rand.Rand) *codectypes.Any { + examples := []*codectypes.Any{ + must(codectypes.NewAnyWithValue(banktypes.NewSendAuthorization(sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(1000))), nil, nil))), + must(codectypes.NewAnyWithValue(authz.NewGenericAuthorization(sdk.MsgTypeURL(&v1.MsgSubmitProposal{})))), + } + return examples[r.Intn(len(examples))] } -func newAnyAuthorization(a authz.Authorization) *codectypes.Any { - any, err := codectypes.NewAnyWithValue(a) +func must[T any](r T, err error) T { if err != nil { panic(err) } - - return any -} - -// RandomizedGenState generates a random GenesisState for authz. -func RandomizedGenState(simState *module.SimulationState) { - var grants []authz.GrantAuthorization - simState.AppParams.GetOrGenerate("authz", &grants, simState.Rand, func(r *rand.Rand) { - grants = genGrant(r, simState.Accounts, simState.GenTimestamp, simState.AddressCodec) - }) - - authzGrantsGenesis := authz.NewGenesisState(grants) - - simState.GenState[authz.ModuleName] = simState.Cdc.MustMarshalJSON(authzGrantsGenesis) + return r } diff --git a/x/authz/simulation/msg_factory.go b/x/authz/simulation/msg_factory.go new file mode 100644 index 000000000000..ab30a08ffee8 --- /dev/null +++ b/x/authz/simulation/msg_factory.go @@ -0,0 +1,103 @@ +package simulation + +import ( + "context" + "time" + + "cosmossdk.io/x/authz" + "cosmossdk.io/x/authz/keeper" + banktype "cosmossdk.io/x/bank/types" + + "github.com/cosmos/cosmos-sdk/simsx" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +func MsgGrantFactory() simsx.SimMsgFactoryFn[*authz.MsgGrant] { + return func(ctx context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter) ([]simsx.SimAccount, *authz.MsgGrant) { + granter := testData.AnyAccount(reporter, simsx.WithSpendableBalance()) + grantee := testData.AnyAccount(reporter, simsx.ExcludeAccounts(granter)) + spendLimit := granter.LiquidBalance().RandSubsetCoins(reporter, simsx.WithSendEnabledCoins()) + + r := testData.Rand() + var expiration *time.Time + if t1 := r.Timestamp(); !t1.Before(simsx.BlockTime(ctx)) { + expiration = &t1 + } + // pick random authorization + authorizations := []authz.Authorization{ + banktype.NewSendAuthorization(spendLimit, nil, testData.AddressCodec()), + authz.NewGenericAuthorization(sdk.MsgTypeURL(&banktype.MsgSend{})), + } + randomAuthz := simsx.OneOf(r, authorizations) + + msg, err := authz.NewMsgGrant(granter.AddressBech32, grantee.AddressBech32, randomAuthz, expiration) + if err != nil { + reporter.Skip(err.Error()) + return nil, nil + } + return []simsx.SimAccount{granter}, msg + } +} + +func MsgExecFactory(k keeper.Keeper) simsx.SimMsgFactoryFn[*authz.MsgExec] { + return func(ctx context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter) ([]simsx.SimAccount, *authz.MsgExec) { + bankSendOnlyFilter := func(a authz.Authorization) bool { + _, ok := a.(*banktype.SendAuthorization) + return ok + } + granterAddr, granteeAddr, gAuthz := findGrant(ctx, k, reporter, bankSendOnlyFilter) + granter := testData.GetAccountbyAccAddr(reporter, granterAddr) + grantee := testData.GetAccountbyAccAddr(reporter, granteeAddr) + if reporter.IsSkipped() { + return nil, nil + } + amount := granter.LiquidBalance().RandSubsetCoins(reporter, simsx.WithSendEnabledCoins()) + amount = amount.Min(gAuthz.(*banktype.SendAuthorization).SpendLimit) + + payloadMsg := []sdk.Msg{banktype.NewMsgSend(granter.AddressBech32, grantee.AddressBech32, amount)} + msgExec := authz.NewMsgExec(grantee.AddressBech32, payloadMsg) + return []simsx.SimAccount{grantee}, &msgExec + } +} + +func MsgRevokeFactory(k keeper.Keeper) simsx.SimMsgFactoryFn[*authz.MsgRevoke] { + return func(ctx context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter) ([]simsx.SimAccount, *authz.MsgRevoke) { + granterAddr, granteeAddr, auth := findGrant(ctx, k, reporter) + granter := testData.GetAccountbyAccAddr(reporter, granterAddr) + grantee := testData.GetAccountbyAccAddr(reporter, granteeAddr) + if reporter.IsSkipped() { + return nil, nil + } + msgExec := authz.NewMsgRevoke(granter.AddressBech32, grantee.AddressBech32, auth.MsgTypeURL()) + return []simsx.SimAccount{granter}, &msgExec + } +} + +func findGrant( + ctx context.Context, + k keeper.Keeper, + reporter simsx.SimulationReporter, + acceptFilter ...func(a authz.Authorization) bool, +) (granterAddr, granteeAddr sdk.AccAddress, auth authz.Authorization) { + err := k.IterateGrants(ctx, func(granter, grantee sdk.AccAddress, grant authz.Grant) (bool, error) { + a, err2 := grant.GetAuthorization() + if err2 != nil { + return true, err2 + } + for _, filter := range acceptFilter { + if !filter(a) { + return false, nil + } + } + granterAddr, granteeAddr, auth = granter, grantee, a + return true, nil + }) + if err != nil { + reporter.Skip(err.Error()) + return + } + if auth == nil { + reporter.Skip("no grant found") + } + return +} diff --git a/x/authz/simulation/operations.go b/x/authz/simulation/operations.go deleted file mode 100644 index 4c7c085d3b70..000000000000 --- a/x/authz/simulation/operations.go +++ /dev/null @@ -1,394 +0,0 @@ -package simulation - -import ( - "context" - "math/rand" - "time" - - gogoprotoany "github.com/cosmos/gogoproto/types/any" - - "cosmossdk.io/core/address" - "cosmossdk.io/core/appmodule" - corecontext "cosmossdk.io/core/context" - coregas "cosmossdk.io/core/gas" - coreheader "cosmossdk.io/core/header" - "cosmossdk.io/x/authz" - "cosmossdk.io/x/authz/keeper" - banktype "cosmossdk.io/x/bank/types" - - "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/codec" - cdctypes "github.com/cosmos/cosmos-sdk/codec/types" - simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" - sdk "github.com/cosmos/cosmos-sdk/types" - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - simtypes "github.com/cosmos/cosmos-sdk/types/simulation" - "github.com/cosmos/cosmos-sdk/x/simulation" -) - -// authz message types -var ( - TypeMsgGrant = sdk.MsgTypeURL(&authz.MsgGrant{}) - TypeMsgRevoke = sdk.MsgTypeURL(&authz.MsgRevoke{}) - TypeMsgExec = sdk.MsgTypeURL(&authz.MsgExec{}) -) - -// Simulation operation weights constants -const ( - OpWeightMsgGrant = "op_weight_msg_grant" - OpWeightRevoke = "op_weight_msg_revoke" - OpWeightExec = "op_weight_msg_execute" -) - -// authz operations weights -const ( - WeightGrant = 100 - WeightRevoke = 90 - WeightExec = 90 -) - -// WeightedOperations returns all the operations from the module with their respective weights -func WeightedOperations( - registry cdctypes.InterfaceRegistry, - appParams simtypes.AppParams, - cdc codec.JSONCodec, - txGen client.TxConfig, - ak authz.AccountKeeper, - bk authz.BankKeeper, - k keeper.Keeper, -) simulation.WeightedOperations { - var ( - weightMsgGrant int - weightExec int - weightRevoke int - ) - - appParams.GetOrGenerate(OpWeightMsgGrant, &weightMsgGrant, nil, func(_ *rand.Rand) { - weightMsgGrant = WeightGrant - }) - - appParams.GetOrGenerate(OpWeightExec, &weightExec, nil, func(_ *rand.Rand) { - weightExec = WeightExec - }) - - appParams.GetOrGenerate(OpWeightRevoke, &weightRevoke, nil, func(_ *rand.Rand) { - weightRevoke = WeightRevoke - }) - - pCdc := codec.NewProtoCodec(registry) - - return simulation.WeightedOperations{ - simulation.NewWeightedOperation( - weightMsgGrant, - SimulateMsgGrant(pCdc, txGen, ak, bk, k), - ), - simulation.NewWeightedOperation( - weightExec, - SimulateMsgExec(pCdc, txGen, ak, bk, k, registry), - ), - simulation.NewWeightedOperation( - weightRevoke, - SimulateMsgRevoke(pCdc, txGen, ak, bk, k), - ), - } -} - -// SimulateMsgGrant generates a MsgGrant with random values. -func SimulateMsgGrant( - cdc *codec.ProtoCodec, - txCfg client.TxConfig, - ak authz.AccountKeeper, - bk authz.BankKeeper, - _ keeper.Keeper, -) simtypes.Operation { - return func( - r *rand.Rand, app simtypes.AppEntrypoint, ctx sdk.Context, accs []simtypes.Account, chainID string, - ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { - granter, _ := simtypes.RandomAcc(r, accs) - grantee, _ := simtypes.RandomAcc(r, accs) - - if granter.Address.Equals(grantee.Address) { - return simtypes.NoOpMsg(authz.ModuleName, TypeMsgGrant, "granter and grantee are same"), nil, nil - } - - granterAcc := ak.GetAccount(ctx, granter.Address) - spendableCoins := bk.SpendableCoins(ctx, granter.Address) - fees, err := simtypes.RandomFees(r, spendableCoins) - if err != nil { - return simtypes.NoOpMsg(authz.ModuleName, TypeMsgGrant, err.Error()), nil, err - } - - spendLimit := spendableCoins.Sub(fees...) - if len(spendLimit) == 0 { - return simtypes.NoOpMsg(authz.ModuleName, TypeMsgGrant, "spend limit is nil"), nil, nil - } - - var expiration *time.Time - t1 := simtypes.RandTimestamp(r) - if !t1.Before(ctx.HeaderInfo().Time) { - expiration = &t1 - } - randomAuthz := generateRandomAuthorization(r, spendLimit, ak.AddressCodec()) - - granterAddr, err := ak.AddressCodec().BytesToString(granter.Address) - if err != nil { - return simtypes.NoOpMsg(authz.ModuleName, TypeMsgGrant, "could not get granter address"), nil, nil - } - granteeAddr, err := ak.AddressCodec().BytesToString(grantee.Address) - if err != nil { - return simtypes.NoOpMsg(authz.ModuleName, TypeMsgGrant, "could not get grantee address"), nil, nil - } - msg, err := authz.NewMsgGrant(granterAddr, granteeAddr, randomAuthz, expiration) - if err != nil { - return simtypes.NoOpMsg(authz.ModuleName, TypeMsgGrant, err.Error()), nil, err - } - tx, err := simtestutil.GenSignedMockTx( - r, - txCfg, - []sdk.Msg{msg}, - fees, - simtestutil.DefaultGenTxGas, - chainID, - []uint64{granterAcc.GetAccountNumber()}, - []uint64{granterAcc.GetSequence()}, - granter.PrivKey, - ) - if err != nil { - return simtypes.NoOpMsg(authz.ModuleName, TypeMsgGrant, "unable to generate mock tx"), nil, err - } - - _, _, err = app.SimDeliver(txCfg.TxEncoder(), tx) - if err != nil { - return simtypes.NoOpMsg(authz.ModuleName, sdk.MsgTypeURL(msg), "unable to deliver tx"), nil, err - } - return simtypes.NewOperationMsg(msg, true, ""), nil, err - } -} - -func generateRandomAuthorization(r *rand.Rand, spendLimit sdk.Coins, addressCodec address.Codec) authz.Authorization { - authorizations := make([]authz.Authorization, 2) - sendAuthz := banktype.NewSendAuthorization(spendLimit, nil, addressCodec) - authorizations[0] = sendAuthz - authorizations[1] = authz.NewGenericAuthorization(sdk.MsgTypeURL(&banktype.MsgSend{})) - - return authorizations[r.Intn(len(authorizations))] -} - -// SimulateMsgRevoke generates a MsgRevoke with random values. -func SimulateMsgRevoke( - cdc *codec.ProtoCodec, - txCfg client.TxConfig, - ak authz.AccountKeeper, - bk authz.BankKeeper, - k keeper.Keeper, -) simtypes.Operation { - return func( - r *rand.Rand, app simtypes.AppEntrypoint, ctx sdk.Context, accs []simtypes.Account, chainID string, - ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { - var granterAddr, granteeAddr sdk.AccAddress - var grant authz.Grant - hasGrant := false - - err := k.IterateGrants(ctx, func(granter, grantee sdk.AccAddress, g authz.Grant) (bool, error) { - grant = g - granterAddr = granter - granteeAddr = grantee - hasGrant = true - return true, nil - }) - if err != nil { - return simtypes.NoOpMsg(authz.ModuleName, TypeMsgRevoke, err.Error()), nil, err - } - - if !hasGrant { - return simtypes.NoOpMsg(authz.ModuleName, TypeMsgRevoke, "no grants"), nil, nil - } - - granterAcc, ok := simtypes.FindAccount(accs, granterAddr) - if !ok { - return simtypes.NoOpMsg(authz.ModuleName, TypeMsgRevoke, "account not found"), nil, sdkerrors.ErrNotFound.Wrapf("account not found") - } - - spendableCoins := bk.SpendableCoins(ctx, granterAddr) - fees, err := simtypes.RandomFees(r, spendableCoins) - if err != nil { - return simtypes.NoOpMsg(authz.ModuleName, TypeMsgRevoke, "fee error"), nil, err - } - - a, err := grant.GetAuthorization() - if err != nil { - return simtypes.NoOpMsg(authz.ModuleName, TypeMsgRevoke, "authorization error"), nil, err - } - - granterStrAddr, err := ak.AddressCodec().BytesToString(granterAddr) - if err != nil { - return simtypes.NoOpMsg(authz.ModuleName, TypeMsgRevoke, "could not get granter address"), nil, nil - } - granteeStrAddr, err := ak.AddressCodec().BytesToString(granteeAddr) - if err != nil { - return simtypes.NoOpMsg(authz.ModuleName, TypeMsgRevoke, "could not get grantee address"), nil, nil - } - msg := authz.NewMsgRevoke(granterStrAddr, granteeStrAddr, a.MsgTypeURL()) - account := ak.GetAccount(ctx, granterAddr) - tx, err := simtestutil.GenSignedMockTx( - r, - txCfg, - []sdk.Msg{&msg}, - fees, - simtestutil.DefaultGenTxGas, - chainID, - []uint64{account.GetAccountNumber()}, - []uint64{account.GetSequence()}, - granterAcc.PrivKey, - ) - if err != nil { - return simtypes.NoOpMsg(authz.ModuleName, TypeMsgRevoke, err.Error()), nil, err - } - - _, _, err = app.SimDeliver(txCfg.TxEncoder(), tx) - if err != nil { - return simtypes.NoOpMsg(authz.ModuleName, TypeMsgRevoke, "unable to execute tx: "+err.Error()), nil, err - } - - return simtypes.NewOperationMsg(&msg, true, ""), nil, nil - } -} - -// SimulateMsgExec generates a MsgExec with random values. -func SimulateMsgExec( - cdc *codec.ProtoCodec, - txCfg client.TxConfig, - ak authz.AccountKeeper, - bk authz.BankKeeper, - k keeper.Keeper, - unpacker gogoprotoany.AnyUnpacker, -) simtypes.Operation { - return func( - r *rand.Rand, app simtypes.AppEntrypoint, ctx sdk.Context, accs []simtypes.Account, chainID string, - ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { - var granterAddr sdk.AccAddress - var granteeAddr sdk.AccAddress - var sendAuth *banktype.SendAuthorization - var err error - err = k.IterateGrants(ctx, func(granter, grantee sdk.AccAddress, grant authz.Grant) (bool, error) { - granterAddr = granter - granteeAddr = grantee - var a authz.Authorization - a, err = grant.GetAuthorization() - if err != nil { - return true, err - } - var ok bool - sendAuth, ok = a.(*banktype.SendAuthorization) - return ok, nil - }) - if err != nil { - return simtypes.NoOpMsg(authz.ModuleName, TypeMsgExec, err.Error()), nil, err - } - if sendAuth == nil { - return simtypes.NoOpMsg(authz.ModuleName, TypeMsgExec, "no grant found"), nil, nil - } - - grantee, ok := simtypes.FindAccount(accs, granteeAddr) - if !ok { - return simtypes.NoOpMsg(authz.ModuleName, TypeMsgRevoke, "Account not found"), nil, sdkerrors.ErrNotFound.Wrapf("grantee account not found") - } - - if _, ok := simtypes.FindAccount(accs, granterAddr); !ok { - return simtypes.NoOpMsg(authz.ModuleName, TypeMsgRevoke, "Account not found"), nil, sdkerrors.ErrNotFound.Wrapf("granter account not found") - } - - granterspendableCoins := bk.SpendableCoins(ctx, granterAddr) - coins := simtypes.RandSubsetCoins(r, granterspendableCoins) - // if coins slice is empty, we can not create valid banktype.MsgSend - if len(coins) == 0 { - return simtypes.NoOpMsg(authz.ModuleName, TypeMsgExec, "empty coins slice"), nil, nil - } - - // Check send_enabled status of each sent coin denom - if err := bk.IsSendEnabledCoins(ctx, coins...); err != nil { - return simtypes.NoOpMsg(authz.ModuleName, TypeMsgExec, err.Error()), nil, nil - } - - graStr, err := ak.AddressCodec().BytesToString(granterAddr) - if err != nil { - return simtypes.NoOpMsg(authz.ModuleName, TypeMsgExec, err.Error()), nil, err - } - greStr, err := ak.AddressCodec().BytesToString(granteeAddr) - if err != nil { - return simtypes.NoOpMsg(authz.ModuleName, TypeMsgExec, err.Error()), nil, err - } - - msg := []sdk.Msg{banktype.NewMsgSend(graStr, greStr, coins)} - - goCtx := context.WithValue(ctx.Context(), corecontext.EnvironmentContextKey, appmodule.Environment{ - HeaderService: headerService{}, - GasService: mockGasService{}, - }) - - _, err = sendAuth.Accept(goCtx, msg[0]) - if err != nil { - if sdkerrors.ErrInsufficientFunds.Is(err) { - return simtypes.NoOpMsg(authz.ModuleName, TypeMsgExec, err.Error()), nil, nil - } - return simtypes.NoOpMsg(authz.ModuleName, TypeMsgExec, err.Error()), nil, err - - } - - msgExec := authz.NewMsgExec(greStr, msg) - granteeSpendableCoins := bk.SpendableCoins(ctx, granteeAddr) - fees, err := simtypes.RandomFees(r, granteeSpendableCoins) - if err != nil { - return simtypes.NoOpMsg(authz.ModuleName, TypeMsgExec, "fee error"), nil, err - } - - granteeAcc := ak.GetAccount(ctx, granteeAddr) - tx, err := simtestutil.GenSignedMockTx( - r, - txCfg, - []sdk.Msg{&msgExec}, - fees, - simtestutil.DefaultGenTxGas, - chainID, - []uint64{granteeAcc.GetAccountNumber()}, - []uint64{granteeAcc.GetSequence()}, - grantee.PrivKey, - ) - if err != nil { - return simtypes.NoOpMsg(authz.ModuleName, TypeMsgExec, err.Error()), nil, err - } - - _, _, err = app.SimDeliver(txCfg.TxEncoder(), tx) - if err != nil { - return simtypes.NoOpMsg(authz.ModuleName, TypeMsgExec, err.Error()), nil, err - } - - err = msgExec.UnpackInterfaces(unpacker) - if err != nil { - return simtypes.NoOpMsg(authz.ModuleName, TypeMsgExec, "unmarshal error"), nil, err - } - return simtypes.NewOperationMsg(&msgExec, true, "success"), nil, nil - } -} - -type headerService struct{} - -func (h headerService) HeaderInfo(ctx context.Context) coreheader.Info { - return sdk.UnwrapSDKContext(ctx).HeaderInfo() -} - -type mockGasService struct { - coregas.Service -} - -func (m mockGasService) GasMeter(ctx context.Context) coregas.Meter { - return mockGasMeter{} -} - -type mockGasMeter struct { - coregas.Meter -} - -func (m mockGasMeter) Consume(amount coregas.Gas, descriptor string) error { - return nil -} diff --git a/x/authz/testutil/expected_keepers_mocks.go b/x/authz/testutil/expected_keepers_mocks.go index df0bcb0e835f..0a2d645dd6d2 100644 --- a/x/authz/testutil/expected_keepers_mocks.go +++ b/x/authz/testutil/expected_keepers_mocks.go @@ -8,76 +8,10 @@ import ( context "context" reflect "reflect" - address "cosmossdk.io/core/address" types "github.com/cosmos/cosmos-sdk/types" gomock "github.com/golang/mock/gomock" ) -// MockAccountKeeper is a mock of AccountKeeper interface. -type MockAccountKeeper struct { - ctrl *gomock.Controller - recorder *MockAccountKeeperMockRecorder -} - -// MockAccountKeeperMockRecorder is the mock recorder for MockAccountKeeper. -type MockAccountKeeperMockRecorder struct { - mock *MockAccountKeeper -} - -// NewMockAccountKeeper creates a new mock instance. -func NewMockAccountKeeper(ctrl *gomock.Controller) *MockAccountKeeper { - mock := &MockAccountKeeper{ctrl: ctrl} - mock.recorder = &MockAccountKeeperMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockAccountKeeper) EXPECT() *MockAccountKeeperMockRecorder { - return m.recorder -} - -// AddressCodec mocks base method. -func (m *MockAccountKeeper) AddressCodec() address.Codec { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "AddressCodec") - ret0, _ := ret[0].(address.Codec) - return ret0 -} - -// AddressCodec indicates an expected call of AddressCodec. -func (mr *MockAccountKeeperMockRecorder) AddressCodec() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddressCodec", reflect.TypeOf((*MockAccountKeeper)(nil).AddressCodec)) -} - -// GetAccount mocks base method. -func (m *MockAccountKeeper) GetAccount(ctx context.Context, addr types.AccAddress) types.AccountI { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetAccount", ctx, addr) - ret0, _ := ret[0].(types.AccountI) - return ret0 -} - -// GetAccount indicates an expected call of GetAccount. -func (mr *MockAccountKeeperMockRecorder) GetAccount(ctx, addr interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAccount", reflect.TypeOf((*MockAccountKeeper)(nil).GetAccount), ctx, addr) -} - -// NewAccountWithAddress mocks base method. -func (m *MockAccountKeeper) NewAccountWithAddress(ctx context.Context, addr types.AccAddress) types.AccountI { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "NewAccountWithAddress", ctx, addr) - ret0, _ := ret[0].(types.AccountI) - return ret0 -} - -// NewAccountWithAddress indicates an expected call of NewAccountWithAddress. -func (mr *MockAccountKeeperMockRecorder) NewAccountWithAddress(ctx, addr interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NewAccountWithAddress", reflect.TypeOf((*MockAccountKeeper)(nil).NewAccountWithAddress), ctx, addr) -} - // MockBankKeeper is a mock of BankKeeper interface. type MockBankKeeper struct { ctrl *gomock.Controller diff --git a/x/bank/CHANGELOG.md b/x/bank/CHANGELOG.md index f226eac88503..7cfd8ed0410b 100644 --- a/x/bank/CHANGELOG.md +++ b/x/bank/CHANGELOG.md @@ -35,13 +35,14 @@ Ref: https://keepachangelog.com/en/1.0.0/ * [#18636](https://github.com/cosmos/cosmos-sdk/pull/18636) `SendCoinsFromModuleToAccount`, `SendCoinsFromModuleToModule`, `SendCoinsFromAccountToModule`, `DelegateCoinsFromAccountToModule`, `UndelegateCoinsFromModuleToAccount`, `MintCoins` and `BurnCoins` methods now returns an error instead of panicking if any module accounts does not exist or unauthorized. * [#20517](https://github.com/cosmos/cosmos-sdk/pull/20517) `SendCoins` now checks for `SendRestrictions` before instead of after deducting coins using `subUnlockedCoins`. * [#20354](https://github.com/cosmos/cosmos-sdk/pull/20354) Reduce the number of `ValidateDenom` calls in `bank.SendCoins`. +* [#21976](https://github.com/cosmos/cosmos-sdk/pull/21976) Resolve a footgun by swapping send restrictions check in `InputOutputCoins` before coin deduction. ### Bug Fixes * [#21407](https://github.com/cosmos/cosmos-sdk/pull/21407) Fix handling of negative spendable balances. - * The `SpendableBalances` query now correctly reports spendable balances when one or more denoms are negative (used to report all zeros). Also, this query now looks up only the balances for the requested page. - * The `SpendableCoins` keeper method now returns the positive spendable balances even when one or more denoms have more locked than available (used to return an empty `Coins`). - * The `SpendableCoin` keeper method now returns a zero coin if there's more locked than available (used to return a negative coin). + * The `SpendableBalances` query now correctly reports spendable balances when one or more denoms are negative (used to report all zeros). Also, this query now looks up only the balances for the requested page. + * The `SpendableCoins` keeper method now returns the positive spendable balances even when one or more denoms have more locked than available (used to return an empty `Coins`). + * The `SpendableCoin` keeper method now returns a zero coin if there's more locked than available (used to return a negative coin). ### API Breaking Changes diff --git a/x/bank/README.md b/x/bank/README.md index 5ac389feb5a2..f6f77f1f947e 100644 --- a/x/bank/README.md +++ b/x/bank/README.md @@ -10,15 +10,13 @@ This document specifies the bank module of the Cosmos SDK. The bank module is responsible for handling multi-asset coin transfers between accounts and tracking special-case pseudo-transfers which must work differently -with particular kinds of accounts (notably delegating/undelegating for vesting +with particular kinds of accounts (notably delegating/undelegating for legacy vesting accounts). It exposes several interfaces with varying capabilities for secure interaction with other modules which must alter user balances. In addition, the bank module tracks and provides query support for the total supply of all assets used in the application. -This module is used in the Cosmos Hub. - ## Contents * [Supply](#supply) @@ -51,9 +49,9 @@ The `supply` functionality: ### Total Supply -The total `Supply` of the network is equal to the sum of all coins from the -account. The total supply is updated every time a `Coin` is minted (eg: as part -of the inflation mechanism) or burned (eg: due to slashing or if a governance +The total `Supply` of the network is equal to the sum of all coins from all +accounts within a chain. The total supply is updated every time a `Coin` is minted +(eg: as part of the inflation mechanism) or burned (eg: due to slashing or if a governance proposal is vetoed). ## Module Accounts @@ -83,13 +81,12 @@ type ModuleAccount interface { > **WARNING!** > Any module or message handler that allows either direct or indirect sending of funds must explicitly guarantee those funds cannot be sent to module accounts (unless allowed). -The supply `Keeper` also introduces new wrapper functions for the auth `Keeper` -and the bank `Keeper` that are related to `ModuleAccount`s in order to be able -to: +The supply `Keeper` interface also introduces new wrapper functions for the auth `Keeper` +and the bank `SendKeeper` in order to be able to: -* Get and set `ModuleAccount`s by providing the `Name`. -* Send coins from and to other `ModuleAccount`s or standard `Account`s - (`BaseAccount` or `VestingAccount`) by passing only the `Name`. +* Get `ModuleAccount`s by providing its `Name`. +* Send coins from and to other `ModuleAccount`s by passing only the `Name` or standard `Account`s + (`BaseAccount` or legacy `VestingAccount`). * `Mint` or `Burn` coins for a `ModuleAccount` (restricted to its permissions). ### Permissions @@ -122,6 +119,7 @@ aforementioned state: * Denom Metadata Index: `0x1 | byte(denom) -> ProtocolBuffer(Metadata)` * Balances Index: `0x2 | byte(address length) | []byte(address) | []byte(balance.Denom) -> ProtocolBuffer(balance)` * Reverse Denomination to Address Index: `0x03 | byte(denom) | 0x00 | []byte(address) -> 0` +* Send enabled Denoms: `0x4 | string -> bool` ## Params @@ -131,7 +129,7 @@ it can be updated with governance or the address with authority. * Params: `0x05 | ProtocolBuffer(Params)` ```protobuf reference -https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/bank/v1beta1/bank.proto#L12-L23 +https://github.com/cosmos/cosmos-sdk/blob/v0.52.0-beta.1/x/bank/proto/cosmos/bank/v1beta1/bank.proto#L12-L23 ``` ## Keepers @@ -142,11 +140,11 @@ should use the least-permissive interface that provides the functionality they require. Best practices dictate careful review of `bank` module code to ensure that -permissions are limited in the way that you expect. +permissions are limited in the way that you expected. ### Denied Addresses -The `x/bank` module accepts a map of addresses that are considered blocklisted +The `x/bank` module accepts a map of addresses (`blockedAddrs`) that are considered blocklisted from directly and explicitly receiving funds through means such as `MsgSend` and `MsgMultiSend` and direct API calls like `SendCoinsFromModuleToAccount`. @@ -160,7 +158,7 @@ By providing the `x/bank` module with a blocklisted set of addresses, an error o #### Input -An input of a multiparty transfer +An input of a multi-send transaction ```protobuf // Input models transaction input. @@ -172,7 +170,7 @@ message Input { #### Output -An output of a multiparty transfer. +An output of a multi-send transaction. ```protobuf // Output models transaction outputs. @@ -195,8 +193,8 @@ type Keeper interface { SendKeeper WithMintCoinsRestriction(MintingRestrictionFn) BaseKeeper - InitGenesis(context.Context, *types.GenesisState) - ExportGenesis(context.Context) *types.GenesisState + InitGenesis(context.Context, *types.GenesisState) error + ExportGenesis(context.Context) (*types.GenesisState, error) GetSupply(ctx context.Context, denom string) sdk.Coin HasSupply(ctx context.Context, denom string) bool @@ -213,14 +211,11 @@ type Keeper interface { DelegateCoinsFromAccountToModule(ctx context.Context, senderAddr sdk.AccAddress, recipientModule string, amt sdk.Coins) error UndelegateCoinsFromModuleToAccount(ctx context.Context, senderModule string, recipientAddr sdk.AccAddress, amt sdk.Coins) error MintCoins(ctx context.Context, moduleName string, amt sdk.Coins) error - BurnCoins(ctx context.Context, moduleName string, amt sdk.Coins) error + BurnCoins(ctx context.Context, address []byte, amt sdk.Coins) error DelegateCoins(ctx context.Context, delegatorAddr, moduleAccAddr sdk.AccAddress, amt sdk.Coins) error UndelegateCoins(ctx context.Context, moduleAccAddr, delegatorAddr sdk.AccAddress, amt sdk.Coins) error - // GetAuthority gets the address capable of executing governance proposal messages. Usually the gov module account. - GetAuthority() string - types.QueryServer } ``` @@ -274,17 +269,18 @@ Both functions compose the provided restriction with any previously provided res `AppendSendRestriction` adds the provided restriction to be run after any previously provided send restrictions. `PrependSendRestriction` adds the restriction to be run before any previously provided send restrictions. The composition will short-circuit when an error is encountered. I.e. if the first one returns an error, the second is not run. +Send restrictions can also be cleared by using `ClearSendRestriction`. -During `SendCoins`, the send restriction is applied before coins are removed from the from address and adding them to the to address. -During `InputOutputCoins`, the send restriction is applied after the input coins are removed and once for each output before the funds are added. - -A send restriction function should make use of a custom value in the context to allow bypassing that specific restriction. +During `SendCoins`, the send restriction is applied before coins are removed from the `from_address` and adding them to the `to_address`. +During `InputOutputCoins`, the send restriction is applied before the input coins are removed, once for each output before the funds are added. Send Restrictions are not placed on `ModuleToAccount` or `ModuleToModule` transfers. This is done due to modules needing to move funds to user accounts and other module accounts. This is a design decision to allow for more flexibility in the state machine. The state machine should be able to move funds between module accounts and user accounts without restrictions. Secondly this limitation would limit the usage of the state machine even for itself. users would not be able to receive rewards, not be able to move funds between module accounts. In the case that a user sends funds from a user account to the community pool and then a governance proposal is used to get those tokens into the users account this would fall under the discretion of the app chain developer to what they would like to do here. We can not make strong assumptions here. -Thirdly, this issue could lead into a chain halt if a token is disabled and the token is moved in the begin/endblock. This is the last reason we see the current change and more damaging then beneficial for users. +Thirdly, this issue could lead into a chain halt if a token is disabled and the token is moved in the begin/endblock. This is the last reason we see the current change as they are more damaging then beneficial for users. + +A send restriction function should make use of a custom value in the context to allow bypassing that specific restriction. For example, in your module's keeper package, you'd define the send restriction function: ```golang @@ -337,7 +333,8 @@ func HasBypass(ctx context.Context) bool { } ``` -Now, anywhere where you want to use `SendCoins` or `InputOutputCoins`, but you don't want your send restriction applied: +Now, anywhere where you want to use `SendCoins` or `InputOutputCoins` but you don't want your send restriction applied +you just need to apply custom value in the context: ```golang func (k Keeper) DoThing(ctx context.Context, fromAddr, toAddr sdk.AccAddress, amt sdk.Coins) error { @@ -375,35 +372,35 @@ type ViewKeeper interface { Send coins from one address to another. ```protobuf reference -https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/bank/v1beta1/tx.proto#L38-L53 +https://github.com/cosmos/cosmos-sdk/blob/v0.52.0-beta.1/x/bank/proto/cosmos/bank/v1beta1/tx.proto#L44-L59 ``` The message will fail under the following conditions: * The coins do not have sending enabled -* The `to` address is restricted +* The `to_address` is restricted ### MsgMultiSend -Send coins from one sender and to a series of different address. If any of the receiving addresses do not correspond to an existing account, a new account is created. +Send coins from one sender and to a series of different address. ```protobuf reference -https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/bank/v1beta1/tx.proto#L58-L69 +https://github.com/cosmos/cosmos-sdk/blob/v0.52.0-beta.1/x/bank/proto/cosmos/bank/v1beta1/tx.proto#L65-L75 ``` The message will fail under the following conditions: * Any of the coins do not have sending enabled -* Any of the `to` addresses are restricted +* Any of the `to_address` are restricted * Any of the coins are locked -* The inputs and outputs do not correctly correspond to one another +* The inputs and outputs do not correctly correspond to one another (eg: total_in not equal to total_out) ### MsgUpdateParams The `bank` module params can be updated through `MsgUpdateParams`, which can be done using governance proposal. The signer will always be the `gov` module account address. ```protobuf reference -https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/bank/v1beta1/tx.proto#L74-L88 +https://github.com/cosmos/cosmos-sdk/blob/v0.52.0-beta.1/x/bank/proto/cosmos/bank/v1beta1/tx.proto#L81-L93 ``` The message handling can fail if: @@ -412,30 +409,30 @@ The message handling can fail if: ### MsgSetSendEnabled -Used with the x/gov module to set create/edit SendEnabled entries. +Used with the x/gov module to create or edit SendEnabled entries. ```protobuf reference -https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/bank/v1beta1/tx.proto#L96-L117 +https://github.com/cosmos/cosmos-sdk/blob/v0.52.0-beta.1/x/bank/proto/cosmos/bank/v1beta1/tx.proto#L106-L122 ``` The message will fail under the following conditions: -* The authority is not a decodable address. -* The authority is not x/gov module's address. -* There are multiple SendEnabled entries with the same Denom. -* One or more SendEnabled entries has an invalid Denom. +* The authority is not a decodable address +* The authority is not x/gov module's address +* There are multiple SendEnabled entries with the same Denom +* One or more SendEnabled entries has an invalid Denom ### MsgBurn Used to burn coins from an account. The coins are removed from the account and the total supply is reduced. ```protobuf reference -https://github.com/cosmos/cosmos-sdk/blob/1af000b3ef6296f9928caf494fe5bb812990f22d/proto/cosmos/bank/v1beta1/tx.proto#L131-L148 +https://github.com/cosmos/cosmos-sdk/blob/v0.52.0-beta.1/x/bank/proto/cosmos/bank/v1beta1/tx.proto#L130-L139 ``` This message will fail under the following conditions: -* The signer is not present +* The `from_address` is not a decodable address * The coins are not spendable * The coins are not positive * The coins are not valid @@ -451,20 +448,20 @@ The bank module emits the following events: | Type | Attribute Key | Attribute Value | | -------- | ------------- | ------------------ | | transfer | recipient | {recipientAddress} | +| transfer | sender | {senderAddress} | | transfer | amount | {amount} | | message | module | bank | | message | action | send | -| message | sender | {senderAddress} | #### MsgMultiSend | Type | Attribute Key | Attribute Value | | -------- | ------------- | ------------------ | | transfer | recipient | {recipientAddress} | +| transfer | sender | {senderAddress} | | transfer | amount | {amount} | | message | module | bank | | message | action | multisend | -| message | sender | {senderAddress} | ### Keeper Events @@ -592,9 +589,7 @@ The bank module contains the following parameters ### SendEnabled -The SendEnabled parameter is now deprecated and not to be use. It is replaced -with state store records. - +SendEnabled is depreacted and only kept for backward compatibility. For genesis, use the newly added send_enabled field in the genesis object. Storage, lookup, and manipulation of this information is now in the keeper. ### DefaultSendEnabled @@ -616,6 +611,20 @@ The `query` commands allow users to query `bank` state. simd query bank --help ``` +##### balance + +The `balance` command allows users to query account balance by specific denom. + +```shell +simd query bank balance [address] [denom] [flags] +``` + +Example: + +```shell +simd query bank balance cosmos1.. stake +``` + ##### balances The `balances` command allows users to query account balances by address. @@ -630,49 +639,65 @@ Example: simd query bank balances cosmos1.. ``` -Example Output: +##### spendable balances + +The `spendable-balances` command allows users to query account spendable balances by address. + +```shell +simd query spendable-balances [address] [flags] +``` + +Example: + +```shell +simd query bank spendable-balances cosmos1.. +``` + +##### spendable balance by denom + +The `spendable-balance` command allows users to query account spendable balance by address for a specific denom. + +```shell +simd query spendable-balance [address] [denom] [flags] +``` + +Example: -```yml -balances: -- amount: "1000000000" - denom: stake -pagination: - next_key: null - total: "0" +```shell +simd query bank spendable-balance cosmos1.. stake ``` ##### denom-metadata -The `denom-metadata` command allows users to query metadata for coin denominations. A user can query metadata for a single denomination using the `--denom` flag or all denominations without it. +The `denom-metadata` command allows users to query metadata for coin denominations. ```shell -simd query bank denom-metadata [flags] +simd query bank denom-metadata [denom] ``` Example: ```shell -simd query bank denom-metadata --denom stake +simd query bank denom-metadata stake +``` + +##### denoms-metadata + +The `denoms-metadata` command allows users to query metadata for all coin denominations. + +```shell +simd query bank denoms-metadata [flags] ``` -Example Output: +Example: -```yml -metadata: - base: stake - denom_units: - - aliases: - - STAKE - denom: stake - description: native staking token of simulation app - display: stake - name: SimApp Token - symbol: STK +```shell +simd query bank denoms-metadata ``` -##### total +##### total supply -The `total` command allows users to query the total supply of coins. A user can query the total supply for a single coin using the `--denom` flag or all coins without it. +The `total-supply` (or `total` for short) command allows users to query the total supply of coins. ```shell simd query bank total [flags] @@ -684,11 +709,18 @@ Example: simd query bank total --denom stake ``` -Example Output: +##### total supply of + +The `total-supply-of` command allows users to query the total supply for a specific coin denominations. + +```shell +simd query bank total-supply-of [denom] +``` + +Example: -```yml -amount: "10000000000" -denom: stake +```shell +simd query bank total-supply-of stake ``` ##### send-enabled @@ -705,16 +737,26 @@ Example: simd query bank send-enabled ``` -Example output: +##### params -```yml -send_enabled: -- denom: foocoin - enabled: true -- denom: barcoin -pagination: - next-key: null - total: 2 +The `params` command allows users to query for the current bank parameters. + +```shell +simd query bank params [flags] +``` + +##### denom owners + +The `denom-owners` command allows users to query for all account addresses that own a particular token denomination. + +```shell +simd query bank denom-owners [denom] [flags] +``` + +Example: + +```shell +simd query bank denom-owners stake ``` #### Transactions @@ -760,17 +802,6 @@ grpcurl -plaintext \ cosmos.bank.v1beta1.Query/Balance ``` -Example Output: - -```json -{ - "balance": { - "denom": "stake", - "amount": "1000000000" - } -} -``` - ### AllBalances The `AllBalances` endpoint allows users to query account balance by address for all denominations. @@ -788,22 +819,6 @@ grpcurl -plaintext \ cosmos.bank.v1beta1.Query/AllBalances ``` -Example Output: - -```json -{ - "balances": [ - { - "denom": "stake", - "amount": "1000000000" - } - ], - "pagination": { - "total": "1" - } -} -``` - ### DenomMetadata The `DenomMetadata` endpoint allows users to query metadata for a single coin denomination. @@ -821,28 +836,6 @@ grpcurl -plaintext \ cosmos.bank.v1beta1.Query/DenomMetadata ``` -Example Output: - -```json -{ - "metadata": { - "description": "native staking token of simulation app", - "denomUnits": [ - { - "denom": "stake", - "aliases": [ - "STAKE" - ] - } - ], - "base": "stake", - "display": "stake", - "name": "SimApp Token", - "symbol": "STK" - } -} -``` - ### DenomsMetadata The `DenomsMetadata` endpoint allows users to query metadata for all coin denominations. @@ -859,33 +852,6 @@ grpcurl -plaintext \ cosmos.bank.v1beta1.Query/DenomsMetadata ``` -Example Output: - -```json -{ - "metadatas": [ - { - "description": "native staking token of simulation app", - "denomUnits": [ - { - "denom": "stake", - "aliases": [ - "STAKE" - ] - } - ], - "base": "stake", - "display": "stake", - "name": "SimApp Token", - "symbol": "STK" - } - ], - "pagination": { - "total": "1" - } -} -``` - ### DenomOwners The `DenomOwners` endpoint allows users to query metadata for a single coin denomination. @@ -903,32 +869,6 @@ grpcurl -plaintext \ cosmos.bank.v1beta1.Query/DenomOwners ``` -Example Output: - -```json -{ - "denomOwners": [ - { - "address": "cosmos1..", - "balance": { - "denom": "stake", - "amount": "5000000000" - } - }, - { - "address": "cosmos1..", - "balance": { - "denom": "stake", - "amount": "5000000000" - } - }, - ], - "pagination": { - "total": "2" - } -} -``` - ### TotalSupply The `TotalSupply` endpoint allows users to query the total supply of all coins. @@ -945,22 +885,6 @@ grpcurl -plaintext \ cosmos.bank.v1beta1.Query/TotalSupply ``` -Example Output: - -```json -{ - "supply": [ - { - "denom": "stake", - "amount": "10000000000" - } - ], - "pagination": { - "total": "1" - } -} -``` - ### SupplyOf The `SupplyOf` endpoint allows users to query the total supply of a single coin. @@ -978,17 +902,6 @@ grpcurl -plaintext \ cosmos.bank.v1beta1.Query/SupplyOf ``` -Example Output: - -```json -{ - "amount": { - "denom": "stake", - "amount": "10000000000" - } -} -``` - ### Params The `Params` endpoint allows users to query the parameters of the `bank` module. @@ -1005,16 +918,6 @@ grpcurl -plaintext \ cosmos.bank.v1beta1.Query/Params ``` -Example Output: - -```json -{ - "params": { - "defaultSendEnabled": true - } -} -``` - ### SendEnabled The `SendEnabled` endpoints allows users to query the SendEnabled entries of the `bank` module. @@ -1033,22 +936,3 @@ grpcurl -plaintext \ cosmos.bank.v1beta1.Query/SendEnabled ``` -Example Output: - -```json -{ - "send_enabled": [ - { - "denom": "foocoin", - "enabled": true - }, - { - "denom": "barcoin" - } - ], - "pagination": { - "next-key": null, - "total": 2 - } -} -``` diff --git a/x/bank/client/cli/tx_test.go b/x/bank/client/cli/tx_test.go index 963fa918a29e..8f18458f79de 100644 --- a/x/bank/client/cli/tx_test.go +++ b/x/bank/client/cli/tx_test.go @@ -148,7 +148,6 @@ func (s *CLITestSuite) TestMultiSendTxCmd() { } for _, tc := range testCases { - tc := tc s.Run(tc.name, func() { ctx := svrcmd.CreateExecuteContext(context.Background()) diff --git a/x/bank/go.mod b/x/bank/go.mod index 8371adecaa2a..53fd49dabcd2 100644 --- a/x/bank/go.mod +++ b/x/bank/go.mod @@ -3,9 +3,9 @@ module cosmossdk.io/x/bank go 1.23.1 require ( - cosmossdk.io/api v0.7.5 + cosmossdk.io/api v0.7.6 cosmossdk.io/collections v0.4.0 - cosmossdk.io/core v1.0.0-alpha.2 + cosmossdk.io/core v1.0.0-alpha.4 cosmossdk.io/depinject v1.0.0 cosmossdk.io/errors v1.0.1 cosmossdk.io/log v1.4.1 // indirect @@ -19,17 +19,18 @@ require ( github.com/golang/mock v1.6.0 github.com/golang/protobuf v1.5.4 github.com/grpc-ecosystem/grpc-gateway v1.16.0 - github.com/hashicorp/go-metrics v0.5.3 + github.com/hashicorp/go-metrics v0.5.3 // indirect github.com/spf13/cobra v1.8.1 github.com/stretchr/testify v1.9.0 - google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 - google.golang.org/grpc v1.66.2 + google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 + google.golang.org/grpc v1.67.1 gotest.tools/v3 v3.5.1 ) require ( buf.build/gen/go/cometbft/cometbft/protocolbuffers/go v1.34.2-20240701160653-fedbb9acfd2f.2 // indirect buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.34.2-20240130113600-88ef6483f90f.2 // indirect + cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29 cosmossdk.io/x/staking v0.0.0-00010101000000-000000000000 // indirect cosmossdk.io/x/tx v0.13.3 // indirect filippo.io/edwards25519 v1.1.0 // indirect @@ -49,7 +50,6 @@ require ( github.com/cometbft/cometbft-db v0.15.0 // indirect github.com/cometbft/cometbft/api v1.0.0-rc.1 // indirect github.com/cosmos/btcutil v1.0.5 // indirect - github.com/cosmos/cosmos-db v1.0.3-0.20240911104526-ddc3f09bfc22 // indirect github.com/cosmos/crypto v0.1.2 // indirect github.com/cosmos/go-bip39 v1.0.0 // indirect github.com/cosmos/gogogateway v1.2.0 // indirect @@ -93,7 +93,7 @@ require ( github.com/hashicorp/hcl v1.0.0 // indirect github.com/hashicorp/yamux v0.1.1 // indirect github.com/hdevalence/ed25519consensus v0.2.0 // indirect - github.com/huandu/skiplist v1.2.0 // indirect + github.com/huandu/skiplist v1.2.1 // indirect github.com/iancoleman/strcase v0.3.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jmhodges/levigo v1.0.0 // indirect @@ -115,9 +115,9 @@ require ( github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/client_golang v1.20.3 // indirect + github.com/prometheus/client_golang v1.20.4 // indirect github.com/prometheus/client_model v0.6.1 // indirect - github.com/prometheus/common v0.59.1 // indirect + github.com/prometheus/common v0.60.0 // indirect github.com/prometheus/procfs v0.15.1 // indirect github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect github.com/rogpeppe/go-internal v1.12.0 // indirect @@ -153,7 +153,7 @@ require ( golang.org/x/text v0.18.0 // indirect golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f // indirect google.golang.org/protobuf v1.34.2 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect @@ -161,11 +161,10 @@ require ( sigs.k8s.io/yaml v1.4.0 // indirect ) -require cosmossdk.io/core/testing v0.0.0-00010101000000-000000000000 - require ( - cosmossdk.io/schema v0.2.0 // indirect + cosmossdk.io/schema v0.3.1-0.20240930054013-7c6e0388a3f9 // indirect github.com/cockroachdb/fifo v0.0.0-20240606204812-0bbfbd93a7ce // indirect + github.com/cosmos/cosmos-db v1.0.3-0.20240911104526-ddc3f09bfc22 // indirect github.com/google/uuid v1.6.0 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect ) @@ -176,7 +175,6 @@ replace github.com/cosmos/cosmos-sdk => ../../. replace ( cosmossdk.io/api => ../../api cosmossdk.io/collections => ../../collections - cosmossdk.io/core/testing => ../../core/testing cosmossdk.io/store => ../../store cosmossdk.io/x/staking => ../staking cosmossdk.io/x/tx => ../tx diff --git a/x/bank/go.sum b/x/bank/go.sum index cd6b45de5cf6..7588b565a0d7 100644 --- a/x/bank/go.sum +++ b/x/bank/go.sum @@ -4,8 +4,10 @@ buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.34.2-20240130113600-88e buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.34.2-20240130113600-88ef6483f90f.2/go.mod h1:HqcXMSa5qnNuakaMUo+hWhF51mKbcrZxGl9Vp5EeJXc= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cosmossdk.io/core v1.0.0-alpha.2 h1:epU0Xwces4Rgl5bMhHHkXGaGDcyucNGlC/JDH+Suckg= -cosmossdk.io/core v1.0.0-alpha.2/go.mod h1:abgLjeFLhtuKIYZWSPlVUgQBrKObO7ULV35KYfexE90= +cosmossdk.io/core v1.0.0-alpha.4 h1:9iuroT9ejDYETCsGkzkvs/wAY/5UFl7nCIINFRxyMJY= +cosmossdk.io/core v1.0.0-alpha.4/go.mod h1:3u9cWq1FAVtiiCrDPpo4LhR+9V6k/ycSG4/Y/tREWCY= +cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29 h1:NxxUo0GMJUbIuVg0R70e3cbn9eFTEuMr7ev1AFvypdY= +cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29/go.mod h1:8s2tPeJtSiQuoyPmr2Ag7meikonISO4Fv4MoO8+ORrs= cosmossdk.io/depinject v1.0.0 h1:dQaTu6+O6askNXO06+jyeUAnF2/ssKwrrszP9t5q050= cosmossdk.io/depinject v1.0.0/go.mod h1:zxK/h3HgHoA/eJVtiSsoaRaRA2D5U4cJ5thIG4ssbB8= cosmossdk.io/errors v1.0.1 h1:bzu+Kcr0kS/1DuPBtUFdWjzLqyUuCiyHjyJB6srBV/0= @@ -14,8 +16,8 @@ cosmossdk.io/log v1.4.1 h1:wKdjfDRbDyZRuWa8M+9nuvpVYxrEOwbD/CA8hvhU8QM= cosmossdk.io/log v1.4.1/go.mod h1:k08v0Pyq+gCP6phvdI6RCGhLf/r425UT6Rk/m+o74rU= cosmossdk.io/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE= cosmossdk.io/math v1.3.0/go.mod h1:vnRTxewy+M7BtXBNFybkuhSH4WfedVAAnERHgVFhp3k= -cosmossdk.io/schema v0.2.0 h1:UH5CR1DqUq8yP+5Np8PbvG4YX0zAUsTN2Qk6yThmfMk= -cosmossdk.io/schema v0.2.0/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= +cosmossdk.io/schema v0.3.1-0.20240930054013-7c6e0388a3f9 h1:DmOoS/1PeY6Ih0hAVlJ69kLMUrLV+TCbfICrZtB1vdU= +cosmossdk.io/schema v0.3.1-0.20240930054013-7c6e0388a3f9/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMbk2FiG/kXiLl8BRyzTWDw7gX/Hz7Dd5eDMs= @@ -290,8 +292,8 @@ github.com/hdevalence/ed25519consensus v0.2.0/go.mod h1:w3BHWjwJbFU29IRHL1Iqkw3s github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/huandu/go-assert v1.1.5 h1:fjemmA7sSfYHJD7CUqs9qTwwfdNAx7/j2/ZlHXzNB3c= github.com/huandu/go-assert v1.1.5/go.mod h1:yOLvuqZwmcHIC5rIzrBhT7D3Q9c3GFnd0JrPVhn/06U= -github.com/huandu/skiplist v1.2.0 h1:gox56QD77HzSC0w+Ws3MH3iie755GBJU1OER3h5VsYw= -github.com/huandu/skiplist v1.2.0/go.mod h1:7v3iFjLcSAzO4fN5B8dvebvo/qsfumiLiDXMrPiHF9w= +github.com/huandu/skiplist v1.2.1 h1:dTi93MgjwErA/8idWTzIw4Y1kZsMWx35fmI2c8Rij7w= +github.com/huandu/skiplist v1.2.1/go.mod h1:7v3iFjLcSAzO4fN5B8dvebvo/qsfumiLiDXMrPiHF9w= github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI= github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= @@ -400,8 +402,8 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= -github.com/prometheus/client_golang v1.20.3 h1:oPksm4K8B+Vt35tUhw6GbSNSgVlVSBH0qELP/7u83l4= -github.com/prometheus/client_golang v1.20.3/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_golang v1.20.4 h1:Tgh3Yr67PaOv/uTqloMsCEdeuFTatm5zIq5+qNN23vI= +github.com/prometheus/client_golang v1.20.4/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -410,8 +412,8 @@ github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= -github.com/prometheus/common v0.59.1 h1:LXb1quJHWm1P6wq/U824uxYi4Sg0oGvNeUm1z5dJoX0= -github.com/prometheus/common v0.59.1/go.mod h1:GpWM7dewqmVYcd7SmRaiWVe9SSqjf0UrwnYnpEZNuT0= +github.com/prometheus/common v0.60.0 h1:+V9PAREWNvJMAuJ1x1BaWl9dewMW4YrHZQbx0sJNllA= +github.com/prometheus/common v0.60.0/go.mod h1:h0LYf1R1deLSKtD4Vdg8gy4RuOvENW2J/h19V5NADQw= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/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= @@ -634,10 +636,10 @@ google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEY google.golang.org/genproto v0.0.0-20220314164441-57ef72a4c106/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E= google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de h1:F6qOa9AZTYJXOUEr4jDysRDLrm4PHePlge4v4TGAlxY= google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:VUhTRKeHn9wwcdrk73nvdC9gF178Tzhmt/qyaFcPLSo= -google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 h1:+rdxYoE3E5htTEWIe15GlN6IfvbURM//Jt0mmkmm6ZU= -google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117/go.mod h1:OimBR/bc1wPO9iV4NC2bpyjy3VnAwZh5EBPQdtaE5oo= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:pPJltXNxVzT4pK9yD8vR9X75DaWYYmLGMsEvBfFQZzQ= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= +google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 h1:wKguEg1hsxI2/L3hUYrpo1RVi48K+uTyzKqprwLXsb8= +google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142/go.mod h1:d6be+8HhtEtucleCbxpPW9PA9XwISACu8nvpPqF0BVo= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f h1:cUMEy+8oS78BWIH9OWazBkzbr090Od9tWBNtZHkOhf0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= @@ -648,8 +650,8 @@ google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= -google.golang.org/grpc v1.66.2 h1:3QdXkuq3Bkh7w+ywLdLvM56cmGvQHUMZpiCzt6Rqaoo= -google.golang.org/grpc v1.66.2/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y= +google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E= +google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= 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= diff --git a/x/bank/keeper/genesis_test.go b/x/bank/keeper/genesis_test.go index cd08a1178dcb..42f6221092cf 100644 --- a/x/bank/keeper/genesis_test.go +++ b/x/bank/keeper/genesis_test.go @@ -109,7 +109,6 @@ func (suite *KeeperTestSuite) TestTotalSupply() { } for _, tc := range testcases { - tc := tc suite.Run(tc.name, func() { if tc.expErrMsg != "" { suite.Require().ErrorContains(suite.bankKeeper.InitGenesis(suite.ctx, tc.genesis), tc.expErrMsg) diff --git a/x/bank/keeper/grpc_query_test.go b/x/bank/keeper/grpc_query_test.go index c563e4b60f66..6de9321d404c 100644 --- a/x/bank/keeper/grpc_query_test.go +++ b/x/bank/keeper/grpc_query_test.go @@ -83,8 +83,6 @@ func (suite *KeeperTestSuite) TestQueryBalance() { } for _, tc := range testCases { - tc := tc - suite.Run(tc.name, func() { res, err := queryClient.Balance(gocontext.Background(), tc.req) if tc.expectErrMsg == "" { diff --git a/x/bank/keeper/keeper_test.go b/x/bank/keeper/keeper_test.go index 120e8a2537f7..4fe765039638 100644 --- a/x/bank/keeper/keeper_test.go +++ b/x/bank/keeper/keeper_test.go @@ -790,6 +790,7 @@ func (suite *KeeperTestSuite) TestInputOutputCoinsWithRestrictions() { suite.Require().NoError(err) fromAcc := authtypes.NewBaseAccountWithAddress(fromAddr) inputAccs := []sdk.AccountI{fromAcc} + suite.authKeeper.EXPECT().GetAccount(suite.ctx, inputAccs[0].GetAddress()).Return(inputAccs[0]).AnyTimes() toAddr1 := accAddrs[1] toAddr1Str, err := suite.authKeeper.AddressCodec().BytesToString(toAddr1) suite.Require().NoError(err) @@ -878,7 +879,7 @@ func (suite *KeeperTestSuite) TestInputOutputCoinsWithRestrictions() { }, expErr: "restriction test error", expBals: expBals{ - from: sdk.NewCoins(newFooCoin(959), newBarCoin(412)), + from: sdk.NewCoins(newFooCoin(959), newBarCoin(500)), to1: sdk.NewCoins(newFooCoin(15)), to2: sdk.NewCoins(newFooCoin(26)), }, @@ -907,7 +908,7 @@ func (suite *KeeperTestSuite) TestInputOutputCoinsWithRestrictions() { }, }, expBals: expBals{ - from: sdk.NewCoins(newFooCoin(948), newBarCoin(400)), + from: sdk.NewCoins(newFooCoin(948), newBarCoin(488)), to1: sdk.NewCoins(newFooCoin(26)), to2: sdk.NewCoins(newFooCoin(26), newBarCoin(12)), }, @@ -937,8 +938,8 @@ func (suite *KeeperTestSuite) TestInputOutputCoinsWithRestrictions() { }, expErr: "second restriction error", expBals: expBals{ - from: sdk.NewCoins(newFooCoin(904), newBarCoin(400)), - to1: sdk.NewCoins(newFooCoin(38)), + from: sdk.NewCoins(newFooCoin(948), newBarCoin(488)), + to1: sdk.NewCoins(newFooCoin(26)), to2: sdk.NewCoins(newFooCoin(26), newBarCoin(12)), }, }, @@ -966,8 +967,8 @@ func (suite *KeeperTestSuite) TestInputOutputCoinsWithRestrictions() { }, }, expBals: expBals{ - from: sdk.NewCoins(newFooCoin(904), newBarCoin(365)), - to1: sdk.NewCoins(newFooCoin(38), newBarCoin(25)), + from: sdk.NewCoins(newFooCoin(948), newBarCoin(453)), + to1: sdk.NewCoins(newFooCoin(26), newBarCoin(25)), to2: sdk.NewCoins(newFooCoin(26), newBarCoin(22)), }, }, @@ -980,7 +981,6 @@ func (suite *KeeperTestSuite) TestInputOutputCoinsWithRestrictions() { actualRestrictionArgs = nil suite.bankKeeper.SetSendRestriction(tc.fn) ctx := suite.ctx - suite.mockInputOutputCoins(inputAccs, tc.outputAddrs) input := banktypes.Input{ Address: fromStrAddr, Coins: tc.inputCoins, @@ -1377,30 +1377,26 @@ func (suite *KeeperTestSuite) TestMsgSendEvents() { suite.mockSendCoins(suite.ctx, acc0, accAddrs[1]) require.NoError(suite.bankKeeper.SendCoins(suite.ctx, accAddrs[0], accAddrs[1], newCoins)) event1 := coreevent.Event{ - Type: banktypes.EventTypeTransfer, - Attributes: []coreevent.Attribute{}, + Type: banktypes.EventTypeTransfer, + Attributes: func() ([]coreevent.Attribute, error) { + return []coreevent.Attribute{ + {Key: banktypes.AttributeKeyRecipient, Value: acc1StrAddr}, + {Key: banktypes.AttributeKeySender, Value: acc0StrAddr}, + {Key: sdk.AttributeKeyAmount, Value: newCoins.String()}, + }, nil + }, } - event1.Attributes = append( - event1.Attributes, - coreevent.Attribute{Key: banktypes.AttributeKeyRecipient, Value: acc1StrAddr}, - ) - event1.Attributes = append( - event1.Attributes, - coreevent.Attribute{Key: banktypes.AttributeKeySender, Value: acc0StrAddr}, - ) - event1.Attributes = append( - event1.Attributes, - coreevent.Attribute{Key: sdk.AttributeKeyAmount, Value: newCoins.String()}, - ) ctx := sdk.UnwrapSDKContext(suite.ctx) // events are shifted due to the funding account events events := ctx.EventManager().Events() require.Equal(8, len(events)) require.Equal(event1.Type, events[7].Type) - for i := range event1.Attributes { - require.Equal(event1.Attributes[i].Key, events[7].Attributes[i].Key) - require.Equal(event1.Attributes[i].Value, events[7].Attributes[i].Value) + attrs, err := event1.Attributes() + require.NoError(err) + for i := range attrs { + require.Equal(attrs[i].Key, events[7].Attributes[i].Key) + require.Equal(attrs[i].Value, events[7].Attributes[i].Value) } } @@ -1462,36 +1458,41 @@ func (suite *KeeperTestSuite) TestMsgMultiSendEvents() { require.Equal(25, len(events)) // 25 due to account funding + coin_spent + coin_recv events event1 := coreevent.Event{ - Type: banktypes.EventTypeTransfer, - Attributes: []coreevent.Attribute{}, + Type: banktypes.EventTypeTransfer, + Attributes: func() ([]coreevent.Attribute, error) { + return []coreevent.Attribute{ + {Key: banktypes.AttributeKeyRecipient, Value: acc2StrAddr}, + {Key: sdk.AttributeKeySender, Value: acc0StrAddr}, + {Key: sdk.AttributeKeyAmount, Value: newCoins.String()}, + }, nil + }, } - event1.Attributes = append( - event1.Attributes, - coreevent.Attribute{Key: banktypes.AttributeKeyRecipient, Value: acc2StrAddr}, - coreevent.Attribute{Key: sdk.AttributeKeySender, Value: acc0StrAddr}, - coreevent.Attribute{Key: sdk.AttributeKeyAmount, Value: newCoins.String()}, - ) event2 := coreevent.Event{ - Type: banktypes.EventTypeTransfer, - Attributes: []coreevent.Attribute{}, + Type: banktypes.EventTypeTransfer, + Attributes: func() ([]coreevent.Attribute, error) { + attrs := []coreevent.Attribute{ + {Key: banktypes.AttributeKeyRecipient, Value: acc3StrAddr}, + {Key: sdk.AttributeKeySender, Value: acc0StrAddr}, + {Key: sdk.AttributeKeyAmount, Value: newCoins2.String()}, + } + return attrs, nil + }, } - event2.Attributes = append( - event2.Attributes, - coreevent.Attribute{Key: banktypes.AttributeKeyRecipient, Value: acc3StrAddr}, - coreevent.Attribute{Key: sdk.AttributeKeySender, Value: acc0StrAddr}, - coreevent.Attribute{Key: sdk.AttributeKeyAmount, Value: newCoins2.String()}, - ) // events are shifted due to the funding account events require.Equal(event1.Type, events[22].Type) - for i := range event1.Attributes { - require.Equal(event1.Attributes[i].Key, events[22].Attributes[i].Key) - require.Equal(event1.Attributes[i].Value, events[22].Attributes[i].Value) + attrs1, err := event1.Attributes() + require.NoError(err) + for i := range attrs1 { + require.Equal(attrs1[i].Key, events[22].Attributes[i].Key) + require.Equal(attrs1[i].Value, events[22].Attributes[i].Value) } require.Equal(event2.Type, events[24].Type) - for i := range event2.Attributes { - require.Equal(event2.Attributes[i].Key, events[24].Attributes[i].Key) - require.Equal(event2.Attributes[i].Value, events[24].Attributes[i].Value) + attrs2, err := event2.Attributes() + require.NoError(err) + for i := range attrs2 { + require.Equal(attrs2[i].Key, events[24].Attributes[i].Key) + require.Equal(attrs2[i].Value, events[24].Attributes[i].Value) } } diff --git a/x/bank/keeper/msg_server.go b/x/bank/keeper/msg_server.go index 5e7b94e13c4c..81d4d2321476 100644 --- a/x/bank/keeper/msg_server.go +++ b/x/bank/keeper/msg_server.go @@ -3,12 +3,9 @@ package keeper import ( "context" - "github.com/hashicorp/go-metrics" - errorsmod "cosmossdk.io/errors" "cosmossdk.io/x/bank/types" - "github.com/cosmos/cosmos-sdk/telemetry" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" ) @@ -65,18 +62,6 @@ func (k msgServer) Send(ctx context.Context, msg *types.MsgSend) (*types.MsgSend return nil, err } - defer func() { - for _, a := range msg.Amount { - if a.Amount.IsInt64() { - telemetry.SetGaugeWithLabels( - []string{"tx", "msg", "send"}, - float32(a.Amount.Int64()), - []metrics.Label{telemetry.NewLabel("denom", a.Denom)}, - ) - } - } - }() - return &types.MsgSendResponse{}, nil } diff --git a/x/bank/keeper/msg_server_test.go b/x/bank/keeper/msg_server_test.go index ecc09f79ba78..c02f6943b90a 100644 --- a/x/bank/keeper/msg_server_test.go +++ b/x/bank/keeper/msg_server_test.go @@ -52,7 +52,6 @@ func (suite *KeeperTestSuite) TestMsgUpdateParams() { } for _, tc := range testCases { - tc := tc suite.Run(tc.name, func() { _, err := suite.msgServer.UpdateParams(suite.ctx, tc.input) @@ -145,7 +144,6 @@ func (suite *KeeperTestSuite) TestMsgSend() { } for _, tc := range testCases { - tc := tc suite.Run(tc.name, func() { suite.mockMintCoins(minterAcc) err := suite.bankKeeper.MintCoins(suite.ctx, minterAcc.Name, origCoins) @@ -252,7 +250,6 @@ func (suite *KeeperTestSuite) TestMsgMultiSend() { } for _, tc := range testCases { - tc := tc suite.Run(tc.name, func() { suite.mockMintCoins(minterAcc) err := suite.bankKeeper.MintCoins(suite.ctx, minterAcc.Name, origCoins) @@ -422,7 +419,6 @@ func (suite *KeeperTestSuite) TestMsgBurn() { } for _, tc := range testCases { - tc := tc suite.Run(tc.name, func() { suite.mockMintCoins(multiPermAcc) err := suite.bankKeeper.MintCoins(suite.ctx, multiPermAcc.Name, sdk.Coins{}.Add(origCoins)) diff --git a/x/bank/keeper/send.go b/x/bank/keeper/send.go index 063417b6ca03..929ff2e50285 100644 --- a/x/bank/keeper/send.go +++ b/x/bank/keeper/send.go @@ -148,14 +148,15 @@ func (k BaseSendKeeper) InputOutputCoins(ctx context.Context, input types.Input, return err } - err = k.subUnlockedCoins(ctx, inAddress, input.Coins) - if err != nil { - return err + // ensure all coins can be sent + type toSend struct { + AddressStr string + Address []byte + Coins sdk.Coins } - - var outAddress sdk.AccAddress + sending := make([]toSend, 0) for _, out := range outputs { - outAddress, err = k.ak.AddressCodec().StringToBytes(out.Address) + outAddress, err := k.ak.AddressCodec().StringToBytes(out.Address) if err != nil { return err } @@ -165,13 +166,25 @@ func (k BaseSendKeeper) InputOutputCoins(ctx context.Context, input types.Input, return err } - if err := k.addCoins(ctx, outAddress, out.Coins); err != nil { + sending = append(sending, toSend{ + Address: outAddress, + AddressStr: out.Address, + Coins: out.Coins, + }) + } + + if err := k.subUnlockedCoins(ctx, inAddress, input.Coins); err != nil { + return err + } + + for _, out := range sending { + if err := k.addCoins(ctx, out.Address, out.Coins); err != nil { return err } if err := k.EventService.EventManager(ctx).EmitKV( types.EventTypeTransfer, - event.NewAttribute(types.AttributeKeyRecipient, out.Address), + event.NewAttribute(types.AttributeKeyRecipient, out.AddressStr), event.NewAttribute(types.AttributeKeySender, input.Address), event.NewAttribute(sdk.AttributeKeyAmount, out.Coins.String()), ); err != nil { diff --git a/x/bank/module.go b/x/bank/module.go index 721c3dc6a0cf..49aa2981b918 100644 --- a/x/bank/module.go +++ b/x/bank/module.go @@ -18,6 +18,7 @@ import ( "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/simsx" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/module" simtypes "github.com/cosmos/cosmos-sdk/types/simulation" @@ -160,19 +161,17 @@ func (AppModule) GenerateGenesisState(simState *module.SimulationState) { simulation.RandomizedGenState(simState) } -// ProposalMsgs returns msgs used for governance proposals for simulations. -func (AppModule) ProposalMsgs(simState module.SimulationState) []simtypes.WeightedProposalMsg { - return simulation.ProposalMsgs() -} - // RegisterStoreDecoder registers a decoder for supply module's types func (am AppModule) RegisterStoreDecoder(sdr simtypes.StoreDecoderRegistry) { sdr[types.StoreKey] = simtypes.NewStoreDecoderFuncFromCollectionsSchema(am.keeper.(keeper.BaseKeeper).Schema) } -// WeightedOperations returns the all the gov module operations with their respective weights. -func (am AppModule) WeightedOperations(simState module.SimulationState) []simtypes.WeightedOperation { - return simulation.WeightedOperations( - simState.AppParams, simState.Cdc, simState.TxConfig, am.accountKeeper, am.keeper, - ) +// ProposalMsgsX returns msgs used for governance proposals for simulations. +func (AppModule) ProposalMsgsX(weights simsx.WeightSource, reg simsx.Registry) { + reg.Add(weights.Get("msg_update_params", 100), simulation.MsgUpdateParamsFactory()) +} + +func (am AppModule) WeightedOperationsX(weights simsx.WeightSource, reg simsx.Registry) { + reg.Add(weights.Get("msg_send", 100), simulation.MsgSendFactory()) + reg.Add(weights.Get("msg_multisend", 10), simulation.MsgMultiSendFactory()) } diff --git a/x/bank/proto/cosmos/bank/module/v2/module.proto b/x/bank/proto/cosmos/bank/module/v2/module.proto index a4c0ed40b52f..4d6db9db5fc6 100644 --- a/x/bank/proto/cosmos/bank/module/v2/module.proto +++ b/x/bank/proto/cosmos/bank/module/v2/module.proto @@ -14,4 +14,10 @@ message Module { // authority defines the custom module authority. If not set, defaults to the governance module. string authority = 1; + + // restrictions_order specifies the order of send restrictions and should be + // a list of module names which provide a send restriction instance. If no + // order is provided, then restrictions will be applied in alphabetical order + // of module names. + repeated string restrictions_order = 2; } diff --git a/x/bank/proto/cosmos/bank/v2/genesis.proto b/x/bank/proto/cosmos/bank/v2/genesis.proto index b73b1d1b4ce8..410baba84b19 100644 --- a/x/bank/proto/cosmos/bank/v2/genesis.proto +++ b/x/bank/proto/cosmos/bank/v2/genesis.proto @@ -4,6 +4,8 @@ package cosmos.bank.v2; import "gogoproto/gogo.proto"; import "cosmos/bank/v2/bank.proto"; import "amino/amino.proto"; +import "cosmos/base/v1beta1/coin.proto"; +import "cosmos_proto/cosmos.proto"; option go_package = "cosmossdk.io/x/bank/v2/types"; @@ -11,4 +13,34 @@ option go_package = "cosmossdk.io/x/bank/v2/types"; message GenesisState { // params defines all the parameters of the module. Params params = 1 [(gogoproto.nullable) = false, (amino.dont_omitempty) = true]; + + // balances is an array containing the balances of all the accounts. + repeated Balance balances = 2 [(gogoproto.nullable) = false, (amino.dont_omitempty) = true]; + + // supply represents the total supply. If it is left empty, then supply will be calculated based on the provided + // balances. Otherwise, it will be used to validate that the sum of the balances equals this amount. + repeated cosmos.base.v1beta1.Coin supply = 3 [ + (amino.encoding) = "legacy_coins", + (gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins", + (gogoproto.nullable) = false, + (amino.dont_omitempty) = true + ]; +} + +// Balance defines an account address and balance pair used in the bank module's +// genesis state. +message Balance { + option (gogoproto.equal) = false; + option (gogoproto.goproto_getters) = false; + + // address is the address of the balance holder. + string address = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"]; + + // coins defines the different coins this balance holds. + repeated cosmos.base.v1beta1.Coin coins = 2 [ + (amino.encoding) = "legacy_coins", + (gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins", + (gogoproto.nullable) = false, + (amino.dont_omitempty) = true + ]; } \ No newline at end of file diff --git a/x/bank/proto/cosmos/bank/v2/query.proto b/x/bank/proto/cosmos/bank/v2/query.proto index 4ec5a445635e..4b47915b0baf 100644 --- a/x/bank/proto/cosmos/bank/v2/query.proto +++ b/x/bank/proto/cosmos/bank/v2/query.proto @@ -4,6 +4,8 @@ package cosmos.bank.v2; import "gogoproto/gogo.proto"; import "amino/amino.proto"; import "cosmos/bank/v2/bank.proto"; +import "cosmos/base/v1beta1/coin.proto"; +import "cosmos_proto/cosmos.proto"; option go_package = "cosmossdk.io/x/bank/v2/types"; @@ -14,4 +16,22 @@ message QueryParamsRequest {} message QueryParamsResponse { // params provides the parameters of the bank module. Params params = 1 [(gogoproto.nullable) = false, (amino.dont_omitempty) = true]; +} + +// QueryBalanceRequest is the request type for the Query/Balance RPC method. +message QueryBalanceRequest { + option (gogoproto.equal) = false; + option (gogoproto.goproto_getters) = false; + + // address is the address to query balances for. + string address = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"]; + + // denom is the coin denom to query balances for. + string denom = 2; +} + +// QueryBalanceResponse is the response type for the Query/Balance RPC method. +message QueryBalanceResponse { + // balance is the balance of the coin. + cosmos.base.v1beta1.Coin balance = 1; } \ No newline at end of file diff --git a/x/bank/proto/cosmos/bank/v2/tx.proto b/x/bank/proto/cosmos/bank/v2/tx.proto index a868e9fcab94..55eab2a9ffd5 100644 --- a/x/bank/proto/cosmos/bank/v2/tx.proto +++ b/x/bank/proto/cosmos/bank/v2/tx.proto @@ -6,6 +6,7 @@ import "cosmos/bank/v2/bank.proto"; import "cosmos_proto/cosmos.proto"; import "cosmos/msg/v1/msg.proto"; import "amino/amino.proto"; +import "cosmos/base/v1beta1/coin.proto"; option go_package = "cosmossdk.io/x/bank/v2/types"; @@ -23,4 +24,42 @@ message MsgUpdateParams { } // MsgUpdateParamsResponse defines the response structure for executing a MsgUpdateParams message. -message MsgUpdateParamsResponse {} \ No newline at end of file +message MsgUpdateParamsResponse {} + +// MsgSend represents a message to send coins from one account to another. +message MsgSend { + option (cosmos.msg.v1.signer) = "from_address"; + option (amino.name) = "cosmos-sdk/x/bank/v2/MsgSend"; + + string from_address = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"]; + string to_address = 2 [(cosmos_proto.scalar) = "cosmos.AddressString"]; + repeated cosmos.base.v1beta1.Coin amount = 3 [ + (gogoproto.nullable) = false, + (amino.dont_omitempty) = true, + (amino.encoding) = "legacy_coins", + (gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins" + ]; +} + +// MsgSendResponse defines the response structure for executing a MsgSend message. +message MsgSendResponse {} + +// MsgMint is the Msg/Mint request type. +message MsgMint { + option (cosmos.msg.v1.signer) = "authority"; + option (amino.name) = "cosmos-sdk/x/bank/v2/MsgMint"; + + // authority is the address that controls the module (defaults to x/gov unless overwritten). + string authority = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"]; + + string to_address = 2 [(cosmos_proto.scalar) = "cosmos.AddressString"]; + repeated cosmos.base.v1beta1.Coin amount = 3 [ + (gogoproto.nullable) = false, + (amino.dont_omitempty) = true, + (amino.encoding) = "legacy_coins", + (gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins" + ]; +} + +// MsgMint defines the response structure for executing a MsgMint message. +message MsgMintResponse {} diff --git a/x/bank/simulation/genesis.go b/x/bank/simulation/genesis.go index 9e8b8512b827..278053099a0e 100644 --- a/x/bank/simulation/genesis.go +++ b/x/bank/simulation/genesis.go @@ -1,8 +1,6 @@ package simulation import ( - "encoding/json" - "fmt" "math/rand" sdkmath "cosmossdk.io/math" @@ -52,7 +50,7 @@ func RandomGenesisSendEnabled(r *rand.Rand, bondDenom string) []types.SendEnable // P(sef) = 18.0% = SendEnabled entry that does not equal the default = P(stc') + P(sfc) = .045 + .135 = .180 // // P(t) = 81.0% = Bond denom is sendable = P(a'c) + P(st) = .360 + .450 = .810 - // P(f) = 19.0% = Bond demon is NOT sendable = P(a'c') + P(sf) = .040 + .150 = .190 + // P(f) = 19.0% = Bond denom is NOT sendable = P(a'c') + P(sf) = .040 + .150 = .190 return rv } @@ -99,10 +97,5 @@ func RandomizedGenState(simState *module.SimulationState) { SendEnabled: sendEnabled, } - paramsBytes, err := json.MarshalIndent(&bankGenesis.Params, "", " ") - if err != nil { - panic(err) - } - fmt.Printf("Selected randomly generated bank parameters:\n%s\n", paramsBytes) simState.GenState[types.ModuleName] = simState.Cdc.MustMarshalJSON(&bankGenesis) } diff --git a/x/bank/simulation/genesis_test.go b/x/bank/simulation/genesis_test.go index f5e93943d739..8fea56ada6db 100644 --- a/x/bank/simulation/genesis_test.go +++ b/x/bank/simulation/genesis_test.go @@ -83,8 +83,6 @@ func TestRandomizedGenState1(t *testing.T) { } for _, tt := range tests { - tt := tt - require.Panicsf(t, func() { simulation.RandomizedGenState(&tt.simState) }, tt.panicMsg) } } diff --git a/x/bank/simulation/msg_factory.go b/x/bank/simulation/msg_factory.go new file mode 100644 index 000000000000..ac9a9ff388a2 --- /dev/null +++ b/x/bank/simulation/msg_factory.go @@ -0,0 +1,87 @@ +package simulation + +import ( + "context" + "slices" + + "cosmossdk.io/x/bank/types" + + "github.com/cosmos/cosmos-sdk/simsx" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +func MsgSendFactory() simsx.SimMsgFactoryFn[*types.MsgSend] { + return func(ctx context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter) ([]simsx.SimAccount, *types.MsgSend) { + from := testData.AnyAccount(reporter, simsx.WithSpendableBalance()) + to := testData.AnyAccount(reporter, simsx.ExcludeAccounts(from)) + coins := from.LiquidBalance().RandSubsetCoins(reporter, simsx.WithSendEnabledCoins()) + return []simsx.SimAccount{from}, types.NewMsgSend(from.AddressBech32, to.AddressBech32, coins) + } +} + +func MsgMultiSendFactory() simsx.SimMsgFactoryFn[*types.MsgMultiSend] { + return func(ctx context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter) ([]simsx.SimAccount, *types.MsgMultiSend) { + r := testData.Rand() + var ( + sending = make([]types.Input, 1) + receiving = make([]types.Output, r.Intn(3)+1) + senderAcc = make([]simsx.SimAccount, len(sending)) + totalSentCoins sdk.Coins + uniqueAccountsFilter = simsx.UniqueAccounts() + ) + for i := range sending { + // generate random input fields, ignore to address + from := testData.AnyAccount(reporter, simsx.WithSpendableBalance(), uniqueAccountsFilter) + if reporter.IsSkipped() { + return nil, nil + } + coins := from.LiquidBalance().RandSubsetCoins(reporter, simsx.WithSendEnabledCoins()) + + // set signer privkey + senderAcc[i] = from + + // set next input and accumulate total sent coins + sending[i] = types.NewInput(from.AddressBech32, coins) + totalSentCoins = totalSentCoins.Add(coins...) + } + + for i := range receiving { + receiver := testData.AnyAccount(reporter) + if reporter.IsSkipped() { + return nil, nil + } + + var outCoins sdk.Coins + // split total sent coins into random subsets for output + if i == len(receiving)-1 { + // last one receives remaining amount + outCoins = totalSentCoins + } else { + // take random subset of remaining coins for output + // and update remaining coins + outCoins = r.SubsetCoins(totalSentCoins) + totalSentCoins = totalSentCoins.Sub(outCoins...) + } + + receiving[i] = types.NewOutput(receiver.AddressBech32, outCoins) + } + + // remove any entries that have no coins + receiving = slices.DeleteFunc(receiving, func(o types.Output) bool { + return o.Address == "" || o.Coins.Empty() + }) + return senderAcc, &types.MsgMultiSend{Inputs: sending, Outputs: receiving} + } +} + +// MsgUpdateParamsFactory creates a gov proposal for param updates +func MsgUpdateParamsFactory() simsx.SimMsgFactoryFn[*types.MsgUpdateParams] { + return func(_ context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter) ([]simsx.SimAccount, *types.MsgUpdateParams) { + params := types.DefaultParams() + params.DefaultSendEnabled = testData.Rand().Intn(2) == 0 + return nil, &types.MsgUpdateParams{ + Authority: testData.ModuleAccountAddress(reporter, "gov"), + Params: params, + } + } +} diff --git a/x/bank/simulation/operations.go b/x/bank/simulation/operations.go deleted file mode 100644 index d662687cfe07..000000000000 --- a/x/bank/simulation/operations.go +++ /dev/null @@ -1,472 +0,0 @@ -package simulation - -import ( - "math/rand" - - "cosmossdk.io/x/bank/keeper" - "cosmossdk.io/x/bank/types" - - "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/codec" - cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" - simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" - sdk "github.com/cosmos/cosmos-sdk/types" - simtypes "github.com/cosmos/cosmos-sdk/types/simulation" - "github.com/cosmos/cosmos-sdk/x/simulation" -) - -// Simulation operation weights constants -const ( - OpWeightMsgSend = "op_weight_msg_send" - OpWeightMsgMultiSend = "op_weight_msg_multisend" - DefaultWeightMsgSend = 100 // from simappparams.DefaultWeightMsgSend - DefaultWeightMsgMultiSend = 10 // from simappparams.DefaultWeightMsgMultiSend - - distributionModuleName = "distribution" -) - -// WeightedOperations returns all the operations from the module with their respective weights -func WeightedOperations( - appParams simtypes.AppParams, - cdc codec.JSONCodec, - txGen client.TxConfig, - ak types.AccountKeeper, - bk keeper.Keeper, -) simulation.WeightedOperations { - var weightMsgSend, weightMsgMultiSend int - appParams.GetOrGenerate(OpWeightMsgSend, &weightMsgSend, nil, func(_ *rand.Rand) { - weightMsgSend = DefaultWeightMsgSend - }) - - appParams.GetOrGenerate(OpWeightMsgMultiSend, &weightMsgMultiSend, nil, func(_ *rand.Rand) { - weightMsgMultiSend = DefaultWeightMsgMultiSend - }) - - return simulation.WeightedOperations{ - simulation.NewWeightedOperation( - weightMsgSend, - SimulateMsgSend(txGen, ak, bk), - ), - simulation.NewWeightedOperation( - weightMsgMultiSend, - SimulateMsgMultiSend(txGen, ak, bk), - ), - } -} - -// SimulateMsgSend tests and runs a single msg send where both -// accounts already exist. -func SimulateMsgSend( - txGen client.TxConfig, - ak types.AccountKeeper, - bk keeper.Keeper, -) simtypes.Operation { - return func( - r *rand.Rand, app simtypes.AppEntrypoint, ctx sdk.Context, - accs []simtypes.Account, chainID string, - ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { - msgType := sdk.MsgTypeURL(&types.MsgSend{}) - from, to, coins, skip := randomSendFields(r, ctx, accs, bk, ak) - - // if coins slice is empty, we can not create valid types.MsgSend - if len(coins) == 0 { - return simtypes.NoOpMsg(types.ModuleName, msgType, "empty coins slice"), nil, nil - } - - // Check send_enabled status of each coin denom - if err := bk.IsSendEnabledCoins(ctx, coins...); err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, err.Error()), nil, nil - } - if skip { - return simtypes.NoOpMsg(types.ModuleName, msgType, "skip all transfers"), nil, nil - } - - fromstr, err := ak.AddressCodec().BytesToString(from.Address) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, err.Error()), nil, nil - } - tostr, err := ak.AddressCodec().BytesToString(to.Address) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, err.Error()), nil, nil - } - - msg := types.NewMsgSend(fromstr, tostr, coins) - - if err := sendMsgSend(r, app, txGen, bk, ak, msg, ctx, chainID, []cryptotypes.PrivKey{from.PrivKey}); err != nil { - return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(msg), "invalid transfers"), nil, err - } - - return simtypes.NewOperationMsg(msg, true, ""), nil, nil - } -} - -// SimulateMsgSendToModuleAccount tests and runs a single msg send where both -// accounts already exist. -func SimulateMsgSendToModuleAccount( - txGen client.TxConfig, - ak types.AccountKeeper, - bk keeper.Keeper, - moduleAccount int, -) simtypes.Operation { - return func( - r *rand.Rand, app simtypes.AppEntrypoint, ctx sdk.Context, - accs []simtypes.Account, chainID string, - ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { - msgType := sdk.MsgTypeURL(&types.MsgSend{}) - from := accs[0] - to := getModuleAccounts(ak, ctx, moduleAccount)[0] - - spendable := bk.SpendableCoins(ctx, from.Address) - coins := simtypes.RandSubsetCoins(r, spendable) - // if coins slice is empty, we can not create valid types.MsgSend - if len(coins) == 0 { - return simtypes.NoOpMsg(types.ModuleName, msgType, "empty coins slice"), nil, nil - } - // Check send_enabled status of each coin denom - if err := bk.IsSendEnabledCoins(ctx, coins...); err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, err.Error()), nil, nil - } - fromstr, err := ak.AddressCodec().BytesToString(from.Address) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, err.Error()), nil, nil - } - tostr, err := ak.AddressCodec().BytesToString(to.Address) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, err.Error()), nil, nil - } - msg := types.NewMsgSend(fromstr, tostr, coins) - - if err := sendMsgSend(r, app, txGen, bk, ak, msg, ctx, chainID, []cryptotypes.PrivKey{from.PrivKey}); err != nil { - return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(msg), "invalid transfers"), nil, err - } - return simtypes.NewOperationMsg(msg, true, ""), nil, nil - } -} - -// sendMsgSend sends a transaction with a MsgSend from a provided random account. -func sendMsgSend( - r *rand.Rand, app simtypes.AppEntrypoint, - txGen client.TxConfig, - bk keeper.Keeper, ak types.AccountKeeper, - msg *types.MsgSend, ctx sdk.Context, chainID string, privkeys []cryptotypes.PrivKey, -) error { - var ( - fees sdk.Coins - err error - ) - - from, err := ak.AddressCodec().StringToBytes(msg.FromAddress) - if err != nil { - return err - } - - account := ak.GetAccount(ctx, from) - spendable := bk.SpendableCoins(ctx, account.GetAddress()) - - coins, hasNeg := spendable.SafeSub(msg.Amount...) - if !hasNeg { - fees, err = simtypes.RandomFees(r, coins) - if err != nil { - return err - } - } - tx, err := simtestutil.GenSignedMockTx( - r, - txGen, - []sdk.Msg{msg}, - fees, - simtestutil.DefaultGenTxGas, - chainID, - []uint64{account.GetAccountNumber()}, - []uint64{account.GetSequence()}, - privkeys..., - ) - if err != nil { - return err - } - - _, _, err = app.SimDeliver(txGen.TxEncoder(), tx) - if err != nil { - return err - } - - return nil -} - -// SimulateMsgMultiSend tests and runs a single msg multisend, with randomized, capped number of inputs/outputs. -// all accounts in msg fields exist in state -func SimulateMsgMultiSend(txGen client.TxConfig, ak types.AccountKeeper, bk keeper.Keeper) simtypes.Operation { - return func( - r *rand.Rand, app simtypes.AppEntrypoint, ctx sdk.Context, - accs []simtypes.Account, chainID string, - ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { - msgType := sdk.MsgTypeURL(&types.MsgMultiSend{}) - - // random number of inputs/outputs between [1, 3] - inputs := make([]types.Input, r.Intn(1)+1) //nolint:staticcheck // SA4030: (*math/rand.Rand).Intn(n) generates a random value 0 <= x < n; that is, the generated values don't include n; r.Intn(1) therefore always returns 0 - outputs := make([]types.Output, r.Intn(3)+1) - - // collect signer privKeys - privs := make([]cryptotypes.PrivKey, len(inputs)) - - // use map to check if address already exists as input - usedAddrs := make(map[string]bool) - - var totalSentCoins sdk.Coins - for i := range inputs { - // generate random input fields, ignore to address - from, _, coins, skip := randomSendFields(r, ctx, accs, bk, ak) - - fromAddr, err := ak.AddressCodec().BytesToString(from.Address) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "could not retrieve address"), nil, err - } - - // make sure account is fresh and not used in previous input - for usedAddrs[fromAddr] { - from, _, coins, skip = randomSendFields(r, ctx, accs, bk, ak) - } - - if skip { - return simtypes.NoOpMsg(types.ModuleName, msgType, "skip all transfers"), nil, nil - } - - // set input address in used address map - usedAddrs[fromAddr] = true - - // set signer privkey - privs[i] = from.PrivKey - - // set next input and accumulate total sent coins - inputs[i] = types.NewInput(fromAddr, coins) - totalSentCoins = totalSentCoins.Add(coins...) - } - - // Check send_enabled status of each sent coin denom - if err := bk.IsSendEnabledCoins(ctx, totalSentCoins...); err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, err.Error()), nil, nil - } - - for o := range outputs { - out, _ := simtypes.RandomAcc(r, accs) - outAddr, err := ak.AddressCodec().BytesToString(out.Address) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "could not retrieve output address"), nil, err - } - - var outCoins sdk.Coins - // split total sent coins into random subsets for output - if o == len(outputs)-1 { - outCoins = totalSentCoins - } else { - // take random subset of remaining coins for output - // and update remaining coins - outCoins = simtypes.RandSubsetCoins(r, totalSentCoins) - totalSentCoins = totalSentCoins.Sub(outCoins...) - } - - outputs[o] = types.NewOutput(outAddr, outCoins) - } - - // remove any output that has no coins - - for i := 0; i < len(outputs); { - if outputs[i].Coins.Empty() { - outputs[i] = outputs[len(outputs)-1] - outputs = outputs[:len(outputs)-1] - } else { - // continue onto next coin - i++ - } - } - - msg := &types.MsgMultiSend{ - Inputs: inputs, - Outputs: outputs, - } - err := sendMsgMultiSend(r, app, txGen, bk, ak, msg, ctx, chainID, privs) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(msg), "invalid transfers"), nil, err - } - - return simtypes.NewOperationMsg(msg, true, ""), nil, nil - } -} - -// SimulateMsgMultiSendToModuleAccount sends coins to Module Accounts -func SimulateMsgMultiSendToModuleAccount( - txGen client.TxConfig, - ak types.AccountKeeper, - bk keeper.Keeper, - moduleAccount int, -) simtypes.Operation { - return func( - r *rand.Rand, app simtypes.AppEntrypoint, ctx sdk.Context, - accs []simtypes.Account, chainID string, - ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { - msgType := sdk.MsgTypeURL(&types.MsgMultiSend{}) - inputs := make([]types.Input, 2) - outputs := make([]types.Output, moduleAccount) - // collect signer privKeys - privs := make([]cryptotypes.PrivKey, len(inputs)) - var totalSentCoins sdk.Coins - for i := range inputs { - sender := accs[i] - privs[i] = sender.PrivKey - senderAddr, err := ak.AddressCodec().BytesToString(sender.Address) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, err.Error()), nil, err - } - spendable := bk.SpendableCoins(ctx, sender.Address) - coins := simtypes.RandSubsetCoins(r, spendable) - inputs[i] = types.NewInput(senderAddr, coins) - totalSentCoins = totalSentCoins.Add(coins...) - } - if err := bk.IsSendEnabledCoins(ctx, totalSentCoins...); err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, err.Error()), nil, nil - } - moduleAccounts := getModuleAccounts(ak, ctx, moduleAccount) - for i := range outputs { - outAddr, err := ak.AddressCodec().BytesToString(moduleAccounts[i].Address) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "could not retrieve output address"), nil, err - } - - var outCoins sdk.Coins - // split total sent coins into random subsets for output - if i == len(outputs)-1 { - outCoins = totalSentCoins - } else { - // take random subset of remaining coins for output - // and update remaining coins - outCoins = simtypes.RandSubsetCoins(r, totalSentCoins) - totalSentCoins = totalSentCoins.Sub(outCoins...) - } - outputs[i] = types.NewOutput(outAddr, outCoins) - } - // remove any output that has no coins - for i := 0; i < len(outputs); { - if outputs[i].Coins.Empty() { - outputs[i] = outputs[len(outputs)-1] - outputs = outputs[:len(outputs)-1] - } else { - // continue onto next coin - i++ - } - } - msg := &types.MsgMultiSend{ - Inputs: inputs, - Outputs: outputs, - } - err := sendMsgMultiSend(r, app, txGen, bk, ak, msg, ctx, chainID, privs) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(msg), "invalid transfers"), nil, err - } - return simtypes.NewOperationMsg(msg, true, ""), nil, nil - } -} - -// sendMsgMultiSend sends a transaction with a MsgMultiSend from a provided random -// account. -func sendMsgMultiSend( - r *rand.Rand, app simtypes.AppEntrypoint, - txGen client.TxConfig, - bk keeper.Keeper, ak types.AccountKeeper, - msg *types.MsgMultiSend, ctx sdk.Context, chainID string, privkeys []cryptotypes.PrivKey, -) error { - accountNumbers := make([]uint64, len(msg.Inputs)) - sequenceNumbers := make([]uint64, len(msg.Inputs)) - for i := 0; i < len(msg.Inputs); i++ { - addr, err := ak.AddressCodec().StringToBytes(msg.Inputs[i].Address) - if err != nil { - panic(err) - } - - acc := ak.GetAccount(ctx, addr) - accountNumbers[i] = acc.GetAccountNumber() - sequenceNumbers[i] = acc.GetSequence() - } - var ( - fees sdk.Coins - err error - ) - - addr, err := ak.AddressCodec().StringToBytes(msg.Inputs[0].Address) - if err != nil { - panic(err) - } - // feePayer is the first signer, i.e. first input address - feePayer := ak.GetAccount(ctx, addr) - spendable := bk.SpendableCoins(ctx, feePayer.GetAddress()) - coins, hasNeg := spendable.SafeSub(msg.Inputs[0].Coins...) - if !hasNeg { - fees, err = simtypes.RandomFees(r, coins) - if err != nil { - return err - } - } - tx, err := simtestutil.GenSignedMockTx( - r, - txGen, - []sdk.Msg{msg}, - fees, - simtestutil.DefaultGenTxGas, - chainID, - accountNumbers, - sequenceNumbers, - privkeys..., - ) - if err != nil { - return err - } - _, _, err = app.SimDeliver(txGen.TxEncoder(), tx) - if err != nil { - return err - } - return nil -} - -// randomSendFields returns the sender and recipient simulation accounts as well -// as the transferred amount. -func randomSendFields( - r *rand.Rand, ctx sdk.Context, accs []simtypes.Account, bk keeper.Keeper, ak types.AccountKeeper, -) (simtypes.Account, simtypes.Account, sdk.Coins, bool) { - from, _ := simtypes.RandomAcc(r, accs) - to, _ := simtypes.RandomAcc(r, accs) - - // disallow sending money to yourself - for from.PubKey.Equals(to.PubKey) { - to, _ = simtypes.RandomAcc(r, accs) - } - - acc := ak.GetAccount(ctx, from.Address) - if acc == nil { - return from, to, nil, true - } - - spendable := bk.SpendableCoins(ctx, acc.GetAddress()) - - sendCoins := simtypes.RandSubsetCoins(r, spendable) - if sendCoins.Empty() { - return from, to, nil, true - } - - return from, to, sendCoins, false -} - -func getModuleAccounts(ak types.AccountKeeper, ctx sdk.Context, moduleAccount int) []simtypes.Account { - moduleAccounts := make([]simtypes.Account, moduleAccount) - - for i := 0; i < moduleAccount; i++ { - acc := ak.GetModuleAccount(ctx, distributionModuleName) - mAcc := simtypes.Account{ - Address: acc.GetAddress(), - PrivKey: nil, - ConsKey: nil, - PubKey: acc.GetPubKey(), - } - moduleAccounts[i] = mAcc - } - - return moduleAccounts -} diff --git a/x/bank/types/balance_test.go b/x/bank/types/balance_test.go index c208f88c218c..85ed43d035c2 100644 --- a/x/bank/types/balance_test.go +++ b/x/bank/types/balance_test.go @@ -105,7 +105,6 @@ func TestBalanceValidate(t *testing.T) { } for _, tc := range testCases { - tc := tc t.Run(tc.name, func(t *testing.T) { err := tc.balance.Validate() @@ -129,7 +128,6 @@ func TestBalance_GetAddress(t *testing.T) { {"valid address", "cosmos1vy0ga0klndqy92ceqehfkvgmn4t94eteq4hmqv", false}, } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { b := bank.Balance{Address: tt.Address} if !tt.err { diff --git a/x/bank/types/genesis.go b/x/bank/types/genesis.go index 861374e093ea..6f10e7713239 100644 --- a/x/bank/types/genesis.go +++ b/x/bank/types/genesis.go @@ -112,7 +112,7 @@ func GetGenesisStateFromAppState(cdc codec.JSONCodec, appState map[string]json.R // Params.SendEnabled slice is empty, this is a noop. // // If the main SendEnabled slice already has entries, the Params.SendEnabled -// entries are added. In case of the same demon in both, preference is given to +// entries are added. In case of the same denom in both, preference is given to // the existing (main GenesisState field) entry. func (gs *GenesisState) MigrateSendEnabled() { gs.SendEnabled = gs.GetAllSendEnabled() diff --git a/x/bank/types/genesis_test.go b/x/bank/types/genesis_test.go index 93805ac84b57..f7412df117fa 100644 --- a/x/bank/types/genesis_test.go +++ b/x/bank/types/genesis_test.go @@ -146,7 +146,6 @@ func TestGenesisStateValidate(t *testing.T) { } for _, tc := range testCases { - tc := tc t.Run(tc.name, func(tt *testing.T) { err := tc.genesisState.Validate() diff --git a/x/bank/types/metadata_test.go b/x/bank/types/metadata_test.go index 3d8ba100005a..648e13195147 100644 --- a/x/bank/types/metadata_test.go +++ b/x/bank/types/metadata_test.go @@ -217,7 +217,6 @@ func TestMetadataValidate(t *testing.T) { } for _, tc := range testCases { - tc := tc t.Run(tc.name, func(t *testing.T) { err := tc.metadata.Validate() @@ -259,7 +258,6 @@ func TestMarshalJSONMetaData(t *testing.T) { } for _, tc := range testCases { - tc := tc t.Run(tc.name, func(t *testing.T) { bz, err := cdc.MarshalJSON(tc.input) require.NoError(t, err) diff --git a/x/bank/v2/client/cli/query.go b/x/bank/v2/client/cli/query.go new file mode 100644 index 000000000000..2bc0af45f35e --- /dev/null +++ b/x/bank/v2/client/cli/query.go @@ -0,0 +1,79 @@ +package cli + +import ( + "errors" + + gogoproto "github.com/cosmos/gogoproto/proto" + "github.com/spf13/cobra" + + "cosmossdk.io/x/bank/v2/types" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +const ( + FlagDenom = "denom" +) + +// GetQueryCmd returns the parent command for all x/bank CLi query commands. The +// provided clientCtx should have, at a minimum, a verifier, Tendermint RPC client, +// and marshaler set. +func GetQueryCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: types.ModuleName, + Short: "Querying commands for the bank module", + DisableFlagParsing: true, + SuggestionsMinimumDistance: 2, + RunE: client.ValidateCmd, + } + + cmd.AddCommand( + GetBalanceCmd(), + ) + + return cmd +} + +func GetBalanceCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "balance [address] [denom]", + Short: "Query an account balance by address and denom", + Args: cobra.ExactArgs(2), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + + denom := args[1] + if denom == "" { + return errors.New("empty denom") + } + + addr, err := sdk.AccAddressFromBech32(args[0]) + if err != nil { + return err + } + + ctx := cmd.Context() + + req := types.NewQueryBalanceRequest(addr.String(), denom) + out := new(types.QueryBalanceResponse) + + err = clientCtx.Invoke(ctx, gogoproto.MessageName(&types.QueryBalanceRequest{}), req, out) + if err != nil { + return err + } + + return clientCtx.PrintProto(out) + }, + } + + cmd.Flags().String(FlagDenom, "", "The specific balance denomination to query for") + flags.AddQueryFlagsToCmd(cmd) + flags.AddPaginationFlagsToCmd(cmd, "all balances") + + return cmd +} diff --git a/x/bank/v2/client/cli/tx.go b/x/bank/v2/client/cli/tx.go new file mode 100644 index 000000000000..b131c7b62b01 --- /dev/null +++ b/x/bank/v2/client/cli/tx.go @@ -0,0 +1,65 @@ +package cli + +import ( + "github.com/spf13/cobra" + + "cosmossdk.io/x/bank/v2/types" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/cosmos/cosmos-sdk/client/tx" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// TODO: Use AutoCLI commands +// https://github.com/cosmos/cosmos-sdk/issues/21682 +func NewTxCmd() *cobra.Command { + txCmd := &cobra.Command{ + Use: types.ModuleName, + Short: "Bank v2 transaction subcommands", + DisableFlagParsing: true, + SuggestionsMinimumDistance: 2, + RunE: client.ValidateCmd, + } + + txCmd.AddCommand( + NewSendTxCmd(), + ) + + return txCmd +} + +// NewSendTxCmd returns a CLI command handler for creating a MsgSend transaction. +func NewSendTxCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "send [from_key_or_address] [to_address] [amount]", + Short: "Send funds from one account to another.", + Long: `Send funds from one account to another. +Note, the '--from' flag is ignored as it is implied from [from_key_or_address]. +When using '--dry-run' a key name cannot be used, only a bech32 address. +`, + Args: cobra.ExactArgs(3), + RunE: func(cmd *cobra.Command, args []string) error { + if err := cmd.Flags().Set(flags.FlagFrom, args[0]); err != nil { + return err + } + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + coins, err := sdk.ParseCoinsNormalized(args[2]) + if err != nil { + return err + } + + msg := types.NewMsgSend(clientCtx.GetFromAddress().String(), args[1], coins) + + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + }, + } + + flags.AddTxFlagsToCmd(cmd) + + return cmd +} diff --git a/x/bank/v2/depinject.go b/x/bank/v2/depinject.go index b5465d7e02df..6bb04908db2a 100644 --- a/x/bank/v2/depinject.go +++ b/x/bank/v2/depinject.go @@ -1,6 +1,11 @@ package bankv2 import ( + "fmt" + "maps" + "slices" + "sort" + "cosmossdk.io/core/address" "cosmossdk.io/core/appmodule" "cosmossdk.io/depinject" @@ -22,6 +27,7 @@ func init() { appconfig.RegisterModule( &moduletypes.Module{}, appconfig.Provide(ProvideModule), + appconfig.Invoke(InvokeSetSendRestrictions), ) } @@ -61,3 +67,39 @@ func ProvideModule(in ModuleInputs) ModuleOutputs { Module: m, } } + +func InvokeSetSendRestrictions( + config *moduletypes.Module, + keeper keeper.Keeper, + restrictions map[string]types.SendRestrictionFn, +) error { + if config == nil { + return nil + } + + modules := slices.Collect(maps.Keys(restrictions)) + order := config.RestrictionsOrder + if len(order) == 0 { + order = modules + sort.Strings(order) + } + + if len(order) != len(modules) { + return fmt.Errorf("len(restrictions order: %v) != len(restriction modules: %v)", order, modules) + } + + if len(modules) == 0 { + return nil + } + + for _, module := range order { + restriction, ok := restrictions[module] + if !ok { + return fmt.Errorf("can't find send restriction for module %s", module) + } + + keeper.AppendGlobalSendRestriction(restriction) + } + + return nil +} diff --git a/x/bank/v2/keeper/genesis.go b/x/bank/v2/keeper/genesis.go index 05f2abbe5f3b..ac03c9c1331e 100644 --- a/x/bank/v2/keeper/genesis.go +++ b/x/bank/v2/keeper/genesis.go @@ -4,7 +4,10 @@ import ( "context" "fmt" + "cosmossdk.io/collections" "cosmossdk.io/x/bank/v2/types" + + sdk "github.com/cosmos/cosmos-sdk/types" ) // InitGenesis initializes the bank/v2 module genesis state. @@ -13,6 +16,34 @@ func (k *Keeper) InitGenesis(ctx context.Context, state *types.GenesisState) err return fmt.Errorf("failed to set params: %w", err) } + totalSupplyMap := sdk.NewMapCoins(sdk.Coins{}) + + for _, balance := range state.Balances { + addr := balance.Address + bz, err := k.addressCodec.StringToBytes(addr) + if err != nil { + return err + } + + for _, coin := range balance.Coins { + err := k.balances.Set(ctx, collections.Join(bz, coin.Denom), coin.Amount) + if err != nil { + return err + } + } + + totalSupplyMap.Add(balance.Coins...) + } + totalSupply := totalSupplyMap.ToCoins() + + if !state.Supply.Empty() && !state.Supply.Equal(totalSupply) { + return fmt.Errorf("genesis supply is incorrect, expected %v, got %v", state.Supply, totalSupply) + } + + for _, supply := range totalSupply { + k.setSupply(ctx, supply) + } + return nil } diff --git a/x/bank/v2/keeper/handlers.go b/x/bank/v2/keeper/handlers.go index c26b7e4f9cb6..e998aceecb72 100644 --- a/x/bank/v2/keeper/handlers.go +++ b/x/bank/v2/keeper/handlers.go @@ -6,7 +6,14 @@ import ( "errors" "fmt" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + + errorsmod "cosmossdk.io/errors" "cosmossdk.io/x/bank/v2/types" + + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" ) type handlers struct { @@ -45,6 +52,77 @@ func (h handlers) MsgUpdateParams(ctx context.Context, msg *types.MsgUpdateParam return &types.MsgUpdateParamsResponse{}, nil } +func (h handlers) MsgSend(ctx context.Context, msg *types.MsgSend) (*types.MsgSendResponse, error) { + var ( + from, to []byte + err error + ) + + from, err = h.addressCodec.StringToBytes(msg.FromAddress) + if err != nil { + return nil, sdkerrors.ErrInvalidAddress.Wrapf("invalid from address: %s", err) + } + + to, err = h.addressCodec.StringToBytes(msg.ToAddress) + if err != nil { + return nil, sdkerrors.ErrInvalidAddress.Wrapf("invalid to address: %s", err) + } + + if !msg.Amount.IsValid() { + return nil, errorsmod.Wrap(sdkerrors.ErrInvalidCoins, msg.Amount.String()) + } + + if !msg.Amount.IsAllPositive() { + return nil, errorsmod.Wrap(sdkerrors.ErrInvalidCoins, msg.Amount.String()) + } + + // TODO: Check denom enable + + err = h.SendCoins(ctx, from, to, msg.Amount) + if err != nil { + return nil, err + } + + return &types.MsgSendResponse{}, nil +} + +func (h handlers) MsgMint(ctx context.Context, msg *types.MsgMint) (*types.MsgMintResponse, error) { + authorityBytes, err := h.addressCodec.StringToBytes(msg.Authority) + if err != nil { + return nil, err + } + + if !bytes.Equal(h.authority, authorityBytes) { + expectedAuthority, err := h.addressCodec.BytesToString(h.authority) + if err != nil { + return nil, err + } + + return nil, fmt.Errorf("invalid authority; expected %s, got %s", expectedAuthority, msg.Authority) + } + + to, err := h.addressCodec.StringToBytes(msg.ToAddress) + if err != nil { + return nil, sdkerrors.ErrInvalidAddress.Wrapf("invalid to address: %s", err) + } + + if !msg.Amount.IsValid() { + return nil, errorsmod.Wrap(sdkerrors.ErrInvalidCoins, msg.Amount.String()) + } + + if !msg.Amount.IsAllPositive() { + return nil, errorsmod.Wrap(sdkerrors.ErrInvalidCoins, msg.Amount.String()) + } + + // TODO: should mint to mint module then transfer? + err = h.MintCoins(ctx, to, msg.Amount) + if err != nil { + return nil, err + } + + return &types.MsgMintResponse{}, nil +} + // QueryParams queries the parameters of the bank/v2 module. func (h handlers) QueryParams(ctx context.Context, req *types.QueryParamsRequest) (*types.QueryParamsResponse, error) { if req == nil { @@ -58,3 +136,23 @@ func (h handlers) QueryParams(ctx context.Context, req *types.QueryParamsRequest return &types.QueryParamsResponse{Params: params}, nil } + +// QueryBalance queries the parameters of the bank/v2 module. +func (h handlers) QueryBalance(ctx context.Context, req *types.QueryBalanceRequest) (*types.QueryBalanceResponse, error) { + if req == nil { + return nil, errors.New("empty request") + } + + if err := sdk.ValidateDenom(req.Denom); err != nil { + return nil, status.Error(codes.InvalidArgument, err.Error()) + } + + addr, err := h.addressCodec.StringToBytes(req.Address) + if err != nil { + return nil, sdkerrors.ErrInvalidAddress.Wrapf("invalid address: %s", err) + } + + balance := h.Keeper.GetBalance(ctx, addr, req.Denom) + + return &types.QueryBalanceResponse{Balance: &balance}, nil +} diff --git a/x/bank/v2/keeper/keeper.go b/x/bank/v2/keeper/keeper.go index f16982f168c4..833fb298ef6f 100644 --- a/x/bank/v2/keeper/keeper.go +++ b/x/bank/v2/keeper/keeper.go @@ -28,18 +28,21 @@ type Keeper struct { params collections.Item[types.Params] balances *collections.IndexedMap[collections.Pair[[]byte, string], math.Int, BalancesIndexes] supply collections.Map[string, math.Int] + + sendRestriction *sendRestriction } func NewKeeper(authority []byte, addressCodec address.Codec, env appmodulev2.Environment, cdc codec.BinaryCodec) *Keeper { sb := collections.NewSchemaBuilder(env.KVStoreService) k := &Keeper{ - Environment: env, - authority: authority, - addressCodec: addressCodec, // TODO(@julienrbrt): Should we add address codec to the environment? - params: collections.NewItem(sb, types.ParamsKey, "params", codec.CollValue[types.Params](cdc)), - balances: collections.NewIndexedMap(sb, types.BalancesPrefix, "balances", collections.PairKeyCodec(collections.BytesKey, collections.StringKey), sdk.IntValue, newBalancesIndexes(sb)), - supply: collections.NewMap(sb, types.SupplyKey, "supply", collections.StringKey, sdk.IntValue), + Environment: env, + authority: authority, + addressCodec: addressCodec, // TODO(@julienrbrt): Should we add address codec to the environment? + params: collections.NewItem(sb, types.ParamsKey, "params", codec.CollValue[types.Params](cdc)), + balances: collections.NewIndexedMap(sb, types.BalancesPrefix, "balances", collections.PairKeyCodec(collections.BytesKey, collections.StringKey), sdk.IntValue, newBalancesIndexes(sb)), + supply: collections.NewMap(sb, types.SupplyKey, "supply", collections.StringKey, sdk.IntValue), + sendRestriction: newSendRestriction(), } schema, err := sb.Build() @@ -94,7 +97,10 @@ func (k Keeper) SendCoins(ctx context.Context, from, to []byte, amt sdk.Coins) e } var err error - // TODO: Send restriction + to, err = k.sendRestriction.apply(ctx, from, to, amt) + if err != nil { + return err + } err = k.subUnlockedCoins(ctx, from, amt) if err != nil { diff --git a/x/bank/v2/keeper/keeper_test.go b/x/bank/v2/keeper/keeper_test.go index 32ccbac4d2ef..2920d0aea040 100644 --- a/x/bank/v2/keeper/keeper_test.go +++ b/x/bank/v2/keeper/keeper_test.go @@ -1,7 +1,9 @@ package keeper_test import ( + "bytes" "context" + "fmt" "testing" "time" @@ -184,3 +186,53 @@ func (suite *KeeperTestSuite) TestSendCoins_Module_To_Module() { mintBarBalance := suite.bankKeeper.GetBalance(ctx, mintAcc.GetAddress(), barDenom) require.Equal(mintBarBalance.Amount, math.NewInt(0)) } + +func (suite *KeeperTestSuite) TestSendCoins_WithRestriction() { + ctx := suite.ctx + require := suite.Require() + balances := sdk.NewCoins(newFooCoin(100), newBarCoin(50)) + sendAmt := sdk.NewCoins(newFooCoin(10), newBarCoin(10)) + + require.NoError(banktestutil.FundAccount(ctx, suite.bankKeeper, accAddrs[0], balances)) + + // Add first restriction + addrRestrictFunc := func(ctx context.Context, from, to []byte, amount sdk.Coins) ([]byte, error) { + if bytes.Equal(from, to) { + return nil, fmt.Errorf("Can not send to same address") + } + return to, nil + } + suite.bankKeeper.AppendGlobalSendRestriction(addrRestrictFunc) + + err := suite.bankKeeper.SendCoins(ctx, accAddrs[0], accAddrs[0], sendAmt) + require.Error(err) + require.Contains(err.Error(), "Can not send to same address") + + // Add second restriction + amtRestrictFunc := func(ctx context.Context, from, to []byte, amount sdk.Coins) ([]byte, error) { + if len(amount) > 1 { + return nil, fmt.Errorf("Allow only one denom per one send") + } + return to, nil + } + suite.bankKeeper.AppendGlobalSendRestriction(amtRestrictFunc) + + // Pass the 1st but failt at the 2nd + err = suite.bankKeeper.SendCoins(ctx, accAddrs[0], accAddrs[1], sendAmt) + require.Error(err) + require.Contains(err.Error(), "Allow only one denom per one send") + + // Pass both 2 restrictions + err = suite.bankKeeper.SendCoins(ctx, accAddrs[0], accAddrs[1], sdk.NewCoins(newFooCoin(10))) + require.NoError(err) + + // Check balances + acc0FooBalance := suite.bankKeeper.GetBalance(ctx, accAddrs[0], fooDenom) + require.Equal(acc0FooBalance.Amount, math.NewInt(90)) + acc0BarBalance := suite.bankKeeper.GetBalance(ctx, accAddrs[0], barDenom) + require.Equal(acc0BarBalance.Amount, math.NewInt(50)) + acc1FooBalance := suite.bankKeeper.GetBalance(ctx, accAddrs[1], fooDenom) + require.Equal(acc1FooBalance.Amount, math.NewInt(10)) + acc1BarBalance := suite.bankKeeper.GetBalance(ctx, accAddrs[1], barDenom) + require.Equal(acc1BarBalance.Amount, math.ZeroInt()) +} diff --git a/x/bank/v2/keeper/restriction.go b/x/bank/v2/keeper/restriction.go new file mode 100644 index 000000000000..e8d0245615f8 --- /dev/null +++ b/x/bank/v2/keeper/restriction.go @@ -0,0 +1,62 @@ +package keeper + +import ( + "context" + + "cosmossdk.io/x/bank/v2/types" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// sendRestriction is a struct that houses a SendRestrictionFn. +// It exists so that the SendRestrictionFn can be updated in the SendKeeper without needing to have a pointer receiver. +type sendRestriction struct { + fn types.SendRestrictionFn +} + +// newSendRestriction creates a new sendRestriction with nil send restriction. +func newSendRestriction() *sendRestriction { + return &sendRestriction{ + fn: nil, + } +} + +// append adds the provided restriction to this, to be run after the existing function. +func (r *sendRestriction) append(restriction types.SendRestrictionFn) { + r.fn = r.fn.Then(restriction) +} + +// prepend adds the provided restriction to this, to be run before the existing function. +func (r *sendRestriction) prepend(restriction types.SendRestrictionFn) { + r.fn = restriction.Then(r.fn) +} + +// clear removes the send restriction (sets it to nil). +func (r *sendRestriction) clear() { + r.fn = nil +} + +var _ types.SendRestrictionFn = (*sendRestriction)(nil).apply + +// apply applies the send restriction if there is one. If not, it's a no-op. +func (r *sendRestriction) apply(ctx context.Context, fromAddr, toAddr []byte, amt sdk.Coins) ([]byte, error) { + if r == nil || r.fn == nil { + return toAddr, nil + } + return r.fn(ctx, fromAddr, toAddr, amt) +} + +// AppendGlobalSendRestriction adds the provided SendRestrictionFn to run after previously provided global restrictions. +func (k Keeper) AppendGlobalSendRestriction(restriction types.SendRestrictionFn) { + k.sendRestriction.append(restriction) +} + +// PrependGlobalSendRestriction adds the provided SendRestrictionFn to run before previously provided global restrictions. +func (k Keeper) PrependGlobalSendRestriction(restriction types.SendRestrictionFn) { + k.sendRestriction.prepend(restriction) +} + +// ClearGlobalSendRestriction removes the global send restriction (if there is one). +func (k Keeper) ClearGlobalSendRestriction() { + k.sendRestriction.clear() +} diff --git a/x/bank/v2/module.go b/x/bank/v2/module.go index 55cd87d9b4e6..99d5ab2ab7d4 100644 --- a/x/bank/v2/module.go +++ b/x/bank/v2/module.go @@ -3,13 +3,13 @@ package bankv2 import ( "context" "encoding/json" - "errors" "fmt" - gogoproto "github.com/cosmos/gogoproto/proto" + "github.com/spf13/cobra" appmodulev2 "cosmossdk.io/core/appmodule/v2" "cosmossdk.io/core/registry" + "cosmossdk.io/x/bank/v2/client/cli" "cosmossdk.io/x/bank/v2/keeper" "cosmossdk.io/x/bank/v2/types" @@ -95,30 +95,27 @@ func (am AppModule) ExportGenesis(ctx context.Context) (json.RawMessage, error) func (am AppModule) RegisterMsgHandlers(router appmodulev2.MsgRouter) { handlers := keeper.NewHandlers(am.keeper) - var errs error - if err := appmodulev2.RegisterHandler( - router, gogoproto.MessageName(&types.MsgUpdateParams{}), handlers.MsgUpdateParams, - ); err != nil { - errs = errors.Join(errs, err) - } - - if errs != nil { - panic(errs) - } + appmodulev2.RegisterMsgHandler(router, handlers.MsgUpdateParams) + appmodulev2.RegisterMsgHandler(router, handlers.MsgSend) + appmodulev2.RegisterMsgHandler(router, handlers.MsgMint) } // RegisterQueryHandlers registers the query handlers for the bank module. func (am AppModule) RegisterQueryHandlers(router appmodulev2.QueryRouter) { handlers := keeper.NewHandlers(am.keeper) - var errs error - if err := appmodulev2.RegisterHandler( - router, gogoproto.MessageName(&types.QueryParamsRequest{}), handlers.QueryParams, - ); err != nil { - errs = errors.Join(errs, err) - } + appmodulev2.RegisterMsgHandler(router, handlers.QueryParams) + appmodulev2.RegisterMsgHandler(router, handlers.QueryBalance) +} - if errs != nil { - panic(errs) - } +// GetTxCmd returns the root tx command for the bank/v2 module. +// TODO: Remove & use autocli +func (AppModule) GetTxCmd() *cobra.Command { + return cli.NewTxCmd() +} + +// GetQueryCmd returns the root query command for the bank/v2 module. +// TODO: Remove & use autocli +func (AppModule) GetQueryCmd() *cobra.Command { + return cli.GetQueryCmd() } diff --git a/x/bank/v2/types/codec.go b/x/bank/v2/types/codec.go index 75104bbfd0cb..78bca6f3b34b 100644 --- a/x/bank/v2/types/codec.go +++ b/x/bank/v2/types/codec.go @@ -8,5 +8,6 @@ import ( func RegisterInterfaces(registrar registry.InterfaceRegistrar) { registrar.RegisterImplementations((*transaction.Msg)(nil), &MsgUpdateParams{}, + &MsgSend{}, ) } diff --git a/x/bank/v2/types/genesis.pb.go b/x/bank/v2/types/genesis.pb.go index 43432b9f83c2..d2c5e38249e4 100644 --- a/x/bank/v2/types/genesis.pb.go +++ b/x/bank/v2/types/genesis.pb.go @@ -5,6 +5,9 @@ package types import ( fmt "fmt" + _ "github.com/cosmos/cosmos-proto" + github_com_cosmos_cosmos_sdk_types "github.com/cosmos/cosmos-sdk/types" + types "github.com/cosmos/cosmos-sdk/types" _ "github.com/cosmos/cosmos-sdk/types/tx/amino" _ "github.com/cosmos/gogoproto/gogoproto" proto "github.com/cosmos/gogoproto/proto" @@ -28,6 +31,11 @@ const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package type GenesisState struct { // params defines all the parameters of the module. Params Params `protobuf:"bytes,1,opt,name=params,proto3" json:"params"` + // balances is an array containing the balances of all the accounts. + Balances []Balance `protobuf:"bytes,2,rep,name=balances,proto3" json:"balances"` + // supply represents the total supply. If it is left empty, then supply will be calculated based on the provided + // balances. Otherwise, it will be used to validate that the sum of the balances equals this amount. + Supply github_com_cosmos_cosmos_sdk_types.Coins `protobuf:"bytes,3,rep,name=supply,proto3,castrepeated=github.com/cosmos/cosmos-sdk/types.Coins" json:"supply"` } func (m *GenesisState) Reset() { *m = GenesisState{} } @@ -70,27 +78,97 @@ func (m *GenesisState) GetParams() Params { return Params{} } +func (m *GenesisState) GetBalances() []Balance { + if m != nil { + return m.Balances + } + return nil +} + +func (m *GenesisState) GetSupply() github_com_cosmos_cosmos_sdk_types.Coins { + if m != nil { + return m.Supply + } + return nil +} + +// Balance defines an account address and balance pair used in the bank module's +// genesis state. +type Balance struct { + // address is the address of the balance holder. + Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` + // coins defines the different coins this balance holds. + Coins github_com_cosmos_cosmos_sdk_types.Coins `protobuf:"bytes,2,rep,name=coins,proto3,castrepeated=github.com/cosmos/cosmos-sdk/types.Coins" json:"coins"` +} + +func (m *Balance) Reset() { *m = Balance{} } +func (m *Balance) String() string { return proto.CompactTextString(m) } +func (*Balance) ProtoMessage() {} +func (*Balance) Descriptor() ([]byte, []int) { + return fileDescriptor_bc2b1daa12dfd4fc, []int{1} +} +func (m *Balance) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *Balance) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_Balance.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 *Balance) XXX_Merge(src proto.Message) { + xxx_messageInfo_Balance.Merge(m, src) +} +func (m *Balance) XXX_Size() int { + return m.Size() +} +func (m *Balance) XXX_DiscardUnknown() { + xxx_messageInfo_Balance.DiscardUnknown(m) +} + +var xxx_messageInfo_Balance proto.InternalMessageInfo + func init() { proto.RegisterType((*GenesisState)(nil), "cosmos.bank.v2.GenesisState") + proto.RegisterType((*Balance)(nil), "cosmos.bank.v2.Balance") } func init() { proto.RegisterFile("cosmos/bank/v2/genesis.proto", fileDescriptor_bc2b1daa12dfd4fc) } var fileDescriptor_bc2b1daa12dfd4fc = []byte{ - // 198 bytes of a gzipped FileDescriptorProto + // 401 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, 0x4a, 0xcc, 0xcb, 0xd6, 0x2f, 0x33, 0xd2, 0x4f, 0x4f, 0xcd, 0x4b, 0x2d, 0xce, 0x2c, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x83, 0xc8, 0xea, 0x81, 0x64, 0xf5, 0xca, 0x8c, 0xa4, 0x44, 0xd2, 0xf3, 0xd3, 0xf3, 0xc1, 0x52, 0xfa, 0x20, 0x16, 0x44, 0x95, 0x94, 0x24, 0x9a, 0x19, 0x60, 0xd5, 0x10, 0x29, 0xc1, 0xc4, 0xdc, 0xcc, 0xbc, 0x7c, 0x7d, 0x30, 0x09, - 0x11, 0x52, 0xf2, 0xe4, 0xe2, 0x71, 0x87, 0x58, 0x12, 0x5c, 0x92, 0x58, 0x92, 0x2a, 0x64, 0xc9, - 0xc5, 0x56, 0x90, 0x58, 0x94, 0x98, 0x5b, 0x2c, 0xc1, 0xa8, 0xc0, 0xa8, 0xc1, 0x6d, 0x24, 0xa6, - 0x87, 0x6a, 0xa9, 0x5e, 0x00, 0x58, 0xd6, 0x89, 0xf3, 0xc4, 0x3d, 0x79, 0x86, 0x15, 0xcf, 0x37, - 0x68, 0x31, 0x06, 0x41, 0x35, 0x38, 0x99, 0x9d, 0x78, 0x24, 0xc7, 0x78, 0xe1, 0x91, 0x1c, 0xe3, - 0x83, 0x47, 0x72, 0x8c, 0x13, 0x1e, 0xcb, 0x31, 0x5c, 0x78, 0x2c, 0xc7, 0x70, 0xe3, 0xb1, 0x1c, - 0x43, 0x14, 0xd4, 0x5b, 0xc5, 0x29, 0xd9, 0x7a, 0x99, 0xf9, 0xfa, 0x15, 0x70, 0xa7, 0x95, 0x54, - 0x16, 0xa4, 0x16, 0x27, 0xb1, 0x81, 0x5d, 0x62, 0x0c, 0x08, 0x00, 0x00, 0xff, 0xff, 0x29, 0x0d, - 0x99, 0xe2, 0xfd, 0x00, 0x00, 0x00, + 0x15, 0x92, 0x83, 0xab, 0x2e, 0x4e, 0xd5, 0x2f, 0x33, 0x4c, 0x4a, 0x2d, 0x49, 0x34, 0xd4, 0x4f, + 0xce, 0xcf, 0xcc, 0x43, 0x35, 0x2d, 0x1e, 0x62, 0x0d, 0xd4, 0x01, 0x60, 0x8e, 0x52, 0x0b, 0x13, + 0x17, 0x8f, 0x3b, 0xc4, 0x81, 0xc1, 0x25, 0x89, 0x25, 0xa9, 0x42, 0x96, 0x5c, 0x6c, 0x05, 0x89, + 0x45, 0x89, 0xb9, 0xc5, 0x12, 0x8c, 0x0a, 0x8c, 0x1a, 0xdc, 0x46, 0x62, 0x7a, 0xa8, 0x0e, 0xd6, + 0x0b, 0x00, 0xcb, 0x3a, 0x71, 0x9e, 0xb8, 0x27, 0xcf, 0xb0, 0xe2, 0xf9, 0x06, 0x2d, 0xc6, 0x20, + 0xa8, 0x06, 0x21, 0x3b, 0x2e, 0x8e, 0xa4, 0xc4, 0x9c, 0xc4, 0xbc, 0xe4, 0xd4, 0x62, 0x09, 0x26, + 0x05, 0x66, 0x0d, 0x6e, 0x23, 0x71, 0x74, 0xcd, 0x4e, 0x10, 0x79, 0x64, 0xdd, 0x70, 0x3d, 0x42, + 0x95, 0x5c, 0x6c, 0xc5, 0xa5, 0x05, 0x05, 0x39, 0x95, 0x12, 0xcc, 0x60, 0xdd, 0x92, 0x08, 0xdd, + 0xc5, 0xa9, 0x7a, 0x50, 0x7f, 0xe9, 0x39, 0xe7, 0x67, 0xe6, 0x39, 0xb9, 0x81, 0xf4, 0xaf, 0xba, + 0x2f, 0xaf, 0x91, 0x9e, 0x59, 0x92, 0x51, 0x9a, 0xa4, 0x97, 0x9c, 0x9f, 0x0b, 0xf5, 0x17, 0x94, + 0xd2, 0x2d, 0x4e, 0xc9, 0xd6, 0x2f, 0xa9, 0x2c, 0x48, 0x2d, 0x06, 0x6b, 0x28, 0x9e, 0xf5, 0x7c, + 0x83, 0x16, 0x4f, 0x4e, 0x6a, 0x7a, 0x62, 0x72, 0x65, 0x3c, 0x28, 0x64, 0x8a, 0xa1, 0x4e, 0x87, + 0x58, 0xa8, 0x74, 0x80, 0x91, 0x8b, 0x1d, 0xea, 0x36, 0x21, 0x23, 0x2e, 0xf6, 0xc4, 0x94, 0x94, + 0xa2, 0xd4, 0x62, 0x48, 0x10, 0x70, 0x3a, 0x49, 0x5c, 0xda, 0xa2, 0x2b, 0x02, 0x75, 0x8a, 0x23, + 0x44, 0x26, 0xb8, 0xa4, 0x28, 0x33, 0x2f, 0x3d, 0x08, 0xa6, 0x50, 0xa8, 0x9c, 0x8b, 0x15, 0x6c, + 0x2a, 0xd4, 0xdf, 0x74, 0x70, 0x39, 0xc4, 0x3e, 0x2b, 0x8e, 0x8e, 0x05, 0xf2, 0x0c, 0x2f, 0x16, + 0xc8, 0x33, 0x38, 0x99, 0x9d, 0x78, 0x24, 0xc7, 0x78, 0xe1, 0x91, 0x1c, 0xe3, 0x83, 0x47, 0x72, + 0x8c, 0x13, 0x1e, 0xcb, 0x31, 0x5c, 0x78, 0x2c, 0xc7, 0x70, 0xe3, 0xb1, 0x1c, 0x43, 0x14, 0x34, + 0x41, 0x16, 0xa7, 0x64, 0xeb, 0x65, 0xe6, 0xeb, 0x57, 0xc0, 0x13, 0x15, 0xd8, 0x92, 0x24, 0x36, + 0x70, 0x42, 0x30, 0x06, 0x04, 0x00, 0x00, 0xff, 0xff, 0xa0, 0x29, 0x0f, 0xca, 0xb7, 0x02, 0x00, + 0x00, } func (m *GenesisState) Marshal() (dAtA []byte, err error) { @@ -113,6 +191,34 @@ func (m *GenesisState) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if len(m.Supply) > 0 { + for iNdEx := len(m.Supply) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Supply[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenesis(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + } + if len(m.Balances) > 0 { + for iNdEx := len(m.Balances) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Balances[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenesis(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + } { size, err := m.Params.MarshalToSizedBuffer(dAtA[:i]) if err != nil { @@ -126,6 +232,50 @@ func (m *GenesisState) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +func (m *Balance) 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 *Balance) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Balance) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Coins) > 0 { + for iNdEx := len(m.Coins) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Coins[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenesis(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + } + if len(m.Address) > 0 { + i -= len(m.Address) + copy(dAtA[i:], m.Address) + i = encodeVarintGenesis(dAtA, i, uint64(len(m.Address))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + func encodeVarintGenesis(dAtA []byte, offset int, v uint64) int { offset -= sovGenesis(v) base := offset @@ -145,6 +295,37 @@ func (m *GenesisState) Size() (n int) { _ = l l = m.Params.Size() n += 1 + l + sovGenesis(uint64(l)) + if len(m.Balances) > 0 { + for _, e := range m.Balances { + l = e.Size() + n += 1 + l + sovGenesis(uint64(l)) + } + } + if len(m.Supply) > 0 { + for _, e := range m.Supply { + l = e.Size() + n += 1 + l + sovGenesis(uint64(l)) + } + } + return n +} + +func (m *Balance) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Address) + if l > 0 { + n += 1 + l + sovGenesis(uint64(l)) + } + if len(m.Coins) > 0 { + for _, e := range m.Coins { + l = e.Size() + n += 1 + l + sovGenesis(uint64(l)) + } + } return n } @@ -216,6 +397,190 @@ func (m *GenesisState) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Balances", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenesis + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenesis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Balances = append(m.Balances, Balance{}) + if err := m.Balances[len(m.Balances)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Supply", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenesis + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenesis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Supply = append(m.Supply, types.Coin{}) + if err := m.Supply[len(m.Supply)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenesis(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenesis + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *Balance) 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 ErrIntOverflowGenesis + } + 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: Balance: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Balance: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Address", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenesis + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGenesis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Address = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Coins", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenesis + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenesis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Coins = append(m.Coins, types.Coin{}) + if err := m.Coins[len(m.Coins)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipGenesis(dAtA[iNdEx:]) diff --git a/x/bank/v2/types/module/module.pb.go b/x/bank/v2/types/module/module.pb.go index 247cbd747e3b..d752f9ecf933 100644 --- a/x/bank/v2/types/module/module.pb.go +++ b/x/bank/v2/types/module/module.pb.go @@ -27,6 +27,11 @@ const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package type Module struct { // authority defines the custom module authority. If not set, defaults to the governance module. Authority string `protobuf:"bytes,1,opt,name=authority,proto3" json:"authority,omitempty"` + // restrictions_order specifies the order of send restrictions and should be + // a list of module names which provide a send restriction instance. If no + // order is provided, then restrictions will be applied in alphabetical order + // of module names. + RestrictionsOrder []string `protobuf:"bytes,2,rep,name=restrictions_order,json=restrictionsOrder,proto3" json:"restrictions_order,omitempty"` } func (m *Module) Reset() { *m = Module{} } @@ -69,6 +74,13 @@ func (m *Module) GetAuthority() string { return "" } +func (m *Module) GetRestrictionsOrder() []string { + if m != nil { + return m.RestrictionsOrder + } + return nil +} + func init() { proto.RegisterType((*Module)(nil), "cosmos.bank.module.v2.Module") } @@ -78,19 +90,21 @@ func init() { } var fileDescriptor_34a109a905e2a25b = []byte{ - // 184 bytes of a gzipped FileDescriptorProto + // 219 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x52, 0x4a, 0xce, 0x2f, 0xce, 0xcd, 0x2f, 0xd6, 0x4f, 0x4a, 0xcc, 0xcb, 0xd6, 0xcf, 0xcd, 0x4f, 0x29, 0xcd, 0x49, 0xd5, 0x2f, 0x33, 0x82, 0xb2, 0xf4, 0x0a, 0x8a, 0xf2, 0x4b, 0xf2, 0x85, 0x44, 0x21, 0x6a, 0xf4, 0x40, 0x6a, 0xf4, 0xa0, 0x32, 0x65, 0x46, 0x52, 0x0a, 0x50, 0xad, 0x89, 0x05, 0x05, 0xfa, 0x65, 0x86, 0x89, - 0x39, 0x05, 0x19, 0x89, 0x86, 0x28, 0x1a, 0x95, 0xdc, 0xb8, 0xd8, 0x7c, 0xc1, 0x7c, 0x21, 0x19, + 0x39, 0x05, 0x19, 0x89, 0x86, 0x28, 0x1a, 0x95, 0x4a, 0xb9, 0xd8, 0x7c, 0xc1, 0x7c, 0x21, 0x19, 0x2e, 0xce, 0xc4, 0xd2, 0x92, 0x8c, 0xfc, 0xa2, 0xcc, 0x92, 0x4a, 0x09, 0x46, 0x05, 0x46, 0x0d, - 0xce, 0x20, 0x84, 0x80, 0x95, 0xdc, 0xae, 0x03, 0xd3, 0x6e, 0x31, 0x4a, 0x70, 0x89, 0x41, 0x4c, - 0x2c, 0x4e, 0xc9, 0xd6, 0xcb, 0xcc, 0xd7, 0xaf, 0x80, 0x38, 0xaa, 0xcc, 0xc8, 0xc9, 0xf6, 0xc4, - 0x23, 0x39, 0xc6, 0x0b, 0x8f, 0xe4, 0x18, 0x1f, 0x3c, 0x92, 0x63, 0x9c, 0xf0, 0x58, 0x8e, 0xe1, - 0xc2, 0x63, 0x39, 0x86, 0x1b, 0x8f, 0xe5, 0x18, 0xa2, 0x94, 0xb1, 0xeb, 0xd0, 0x2f, 0xa9, 0x2c, - 0x48, 0x2d, 0x86, 0x3a, 0x26, 0x89, 0x0d, 0xec, 0x1a, 0x63, 0x40, 0x00, 0x00, 0x00, 0xff, 0xff, - 0x5e, 0xfc, 0x10, 0x2c, 0xec, 0x00, 0x00, 0x00, + 0xce, 0x20, 0x84, 0x80, 0x90, 0x2e, 0x97, 0x50, 0x51, 0x6a, 0x71, 0x49, 0x51, 0x66, 0x72, 0x49, + 0x66, 0x7e, 0x5e, 0x71, 0x7c, 0x7e, 0x51, 0x4a, 0x6a, 0x91, 0x04, 0x93, 0x02, 0xb3, 0x06, 0x67, + 0x90, 0x20, 0xb2, 0x8c, 0x3f, 0x48, 0xc2, 0x4a, 0x6e, 0xd7, 0x81, 0x69, 0xb7, 0x18, 0x25, 0xb8, + 0xc4, 0x20, 0x0e, 0x28, 0x4e, 0xc9, 0xd6, 0xcb, 0xcc, 0xd7, 0xaf, 0x80, 0xf8, 0xa1, 0xcc, 0xc8, + 0xc9, 0xf6, 0xc4, 0x23, 0x39, 0xc6, 0x0b, 0x8f, 0xe4, 0x18, 0x1f, 0x3c, 0x92, 0x63, 0x9c, 0xf0, + 0x58, 0x8e, 0xe1, 0xc2, 0x63, 0x39, 0x86, 0x1b, 0x8f, 0xe5, 0x18, 0xa2, 0x94, 0xb1, 0xeb, 0xd0, + 0x2f, 0xa9, 0x2c, 0x48, 0x2d, 0x86, 0xba, 0x3d, 0x89, 0x0d, 0xec, 0x78, 0x63, 0x40, 0x00, 0x00, + 0x00, 0xff, 0xff, 0x69, 0x6d, 0xb0, 0x10, 0x1b, 0x01, 0x00, 0x00, } func (m *Module) Marshal() (dAtA []byte, err error) { @@ -113,6 +127,15 @@ func (m *Module) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if len(m.RestrictionsOrder) > 0 { + for iNdEx := len(m.RestrictionsOrder) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.RestrictionsOrder[iNdEx]) + copy(dAtA[i:], m.RestrictionsOrder[iNdEx]) + i = encodeVarintModule(dAtA, i, uint64(len(m.RestrictionsOrder[iNdEx]))) + i-- + dAtA[i] = 0x12 + } + } if len(m.Authority) > 0 { i -= len(m.Authority) copy(dAtA[i:], m.Authority) @@ -144,6 +167,12 @@ func (m *Module) Size() (n int) { if l > 0 { n += 1 + l + sovModule(uint64(l)) } + if len(m.RestrictionsOrder) > 0 { + for _, s := range m.RestrictionsOrder { + l = len(s) + n += 1 + l + sovModule(uint64(l)) + } + } return n } @@ -214,6 +243,38 @@ func (m *Module) Unmarshal(dAtA []byte) error { } m.Authority = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field RestrictionsOrder", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowModule + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthModule + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthModule + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.RestrictionsOrder = append(m.RestrictionsOrder, string(dAtA[iNdEx:postIndex])) + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipModule(dAtA[iNdEx:]) diff --git a/x/bank/v2/types/msgs.go b/x/bank/v2/types/msgs.go new file mode 100644 index 000000000000..5b536672eae0 --- /dev/null +++ b/x/bank/v2/types/msgs.go @@ -0,0 +1,14 @@ +package types + +import ( + coretransaction "cosmossdk.io/core/transaction" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +var _ coretransaction.Msg = &MsgSend{} + +// NewMsgSend constructs a msg to send coins from one account to another. +func NewMsgSend(fromAddr, toAddr string, amount sdk.Coins) *MsgSend { + return &MsgSend{FromAddress: fromAddr, ToAddress: toAddr, Amount: amount} +} diff --git a/x/bank/v2/types/query.go b/x/bank/v2/types/query.go new file mode 100644 index 000000000000..b7e932ba5eeb --- /dev/null +++ b/x/bank/v2/types/query.go @@ -0,0 +1,6 @@ +package types + +// NewQueryBalanceRequest creates a new instance of QueryBalanceRequest. +func NewQueryBalanceRequest(addr, denom string) *QueryBalanceRequest { + return &QueryBalanceRequest{Address: addr, Denom: denom} +} diff --git a/x/bank/v2/types/query.pb.go b/x/bank/v2/types/query.pb.go index 9a84957f973c..da09cfc83a44 100644 --- a/x/bank/v2/types/query.pb.go +++ b/x/bank/v2/types/query.pb.go @@ -5,6 +5,8 @@ package types import ( fmt "fmt" + _ "github.com/cosmos/cosmos-proto" + types "github.com/cosmos/cosmos-sdk/types" _ "github.com/cosmos/cosmos-sdk/types/tx/amino" _ "github.com/cosmos/gogoproto/gogoproto" proto "github.com/cosmos/gogoproto/proto" @@ -107,29 +109,126 @@ func (m *QueryParamsResponse) GetParams() Params { return Params{} } +// QueryBalanceRequest is the request type for the Query/Balance RPC method. +type QueryBalanceRequest struct { + // address is the address to query balances for. + Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` + // denom is the coin denom to query balances for. + Denom string `protobuf:"bytes,2,opt,name=denom,proto3" json:"denom,omitempty"` +} + +func (m *QueryBalanceRequest) Reset() { *m = QueryBalanceRequest{} } +func (m *QueryBalanceRequest) String() string { return proto.CompactTextString(m) } +func (*QueryBalanceRequest) ProtoMessage() {} +func (*QueryBalanceRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_bf35183cd83cb842, []int{2} +} +func (m *QueryBalanceRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryBalanceRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryBalanceRequest.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 *QueryBalanceRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryBalanceRequest.Merge(m, src) +} +func (m *QueryBalanceRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryBalanceRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryBalanceRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryBalanceRequest proto.InternalMessageInfo + +// QueryBalanceResponse is the response type for the Query/Balance RPC method. +type QueryBalanceResponse struct { + // balance is the balance of the coin. + Balance *types.Coin `protobuf:"bytes,1,opt,name=balance,proto3" json:"balance,omitempty"` +} + +func (m *QueryBalanceResponse) Reset() { *m = QueryBalanceResponse{} } +func (m *QueryBalanceResponse) String() string { return proto.CompactTextString(m) } +func (*QueryBalanceResponse) ProtoMessage() {} +func (*QueryBalanceResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_bf35183cd83cb842, []int{3} +} +func (m *QueryBalanceResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryBalanceResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryBalanceResponse.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 *QueryBalanceResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryBalanceResponse.Merge(m, src) +} +func (m *QueryBalanceResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryBalanceResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryBalanceResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryBalanceResponse proto.InternalMessageInfo + +func (m *QueryBalanceResponse) GetBalance() *types.Coin { + if m != nil { + return m.Balance + } + return nil +} + func init() { proto.RegisterType((*QueryParamsRequest)(nil), "cosmos.bank.v2.QueryParamsRequest") proto.RegisterType((*QueryParamsResponse)(nil), "cosmos.bank.v2.QueryParamsResponse") + proto.RegisterType((*QueryBalanceRequest)(nil), "cosmos.bank.v2.QueryBalanceRequest") + proto.RegisterType((*QueryBalanceResponse)(nil), "cosmos.bank.v2.QueryBalanceResponse") } func init() { proto.RegisterFile("cosmos/bank/v2/query.proto", fileDescriptor_bf35183cd83cb842) } var fileDescriptor_bf35183cd83cb842 = []byte{ - // 213 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x4a, 0xce, 0x2f, 0xce, - 0xcd, 0x2f, 0xd6, 0x4f, 0x4a, 0xcc, 0xcb, 0xd6, 0x2f, 0x33, 0xd2, 0x2f, 0x2c, 0x4d, 0x2d, 0xaa, - 0xd4, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x83, 0xc8, 0xe9, 0x81, 0xe4, 0xf4, 0xca, 0x8c, - 0xa4, 0x44, 0xd2, 0xf3, 0xd3, 0xf3, 0xc1, 0x52, 0xfa, 0x20, 0x16, 0x44, 0x95, 0x94, 0x60, 0x62, - 0x6e, 0x66, 0x5e, 0xbe, 0x3e, 0x98, 0x84, 0x0a, 0x49, 0xa2, 0x19, 0x0a, 0x36, 0x00, 0x2c, 0xa5, - 0x24, 0xc2, 0x25, 0x14, 0x08, 0xb2, 0x22, 0x20, 0xb1, 0x28, 0x31, 0xb7, 0x38, 0x28, 0xb5, 0xb0, - 0x34, 0xb5, 0xb8, 0x44, 0x29, 0x80, 0x4b, 0x18, 0x45, 0xb4, 0xb8, 0x20, 0x3f, 0xaf, 0x38, 0x55, - 0xc8, 0x92, 0x8b, 0xad, 0x00, 0x2c, 0x22, 0xc1, 0xa8, 0xc0, 0xa8, 0xc1, 0x6d, 0x24, 0xa6, 0x87, - 0xea, 0x22, 0x3d, 0x88, 0x7a, 0x27, 0xce, 0x13, 0xf7, 0xe4, 0x19, 0x56, 0x3c, 0xdf, 0xa0, 0xc5, - 0x18, 0x04, 0xd5, 0xe0, 0x64, 0x76, 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, - 0x32, 0x10, 0x33, 0x8a, 0x53, 0xb2, 0xf5, 0x32, 0xf3, 0xf5, 0x2b, 0xe0, 0x8e, 0x2c, 0xa9, 0x2c, - 0x48, 0x2d, 0x4e, 0x62, 0x03, 0x3b, 0xd3, 0x18, 0x10, 0x00, 0x00, 0xff, 0xff, 0xa7, 0x47, 0xcc, - 0x3c, 0x18, 0x01, 0x00, 0x00, + // 345 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x5c, 0x51, 0x3f, 0x4b, 0xf3, 0x40, + 0x18, 0x4f, 0x5e, 0x78, 0x5b, 0x7b, 0x82, 0x60, 0x0c, 0xd2, 0x16, 0xb9, 0x4a, 0x26, 0x11, 0xbc, + 0xa3, 0x29, 0x08, 0xba, 0x19, 0x47, 0x97, 0x1a, 0x37, 0x17, 0xb9, 0x34, 0x47, 0x09, 0x35, 0xf7, + 0xa4, 0xb9, 0xb4, 0xd8, 0x6f, 0xe0, 0xe8, 0x47, 0xe8, 0xe8, 0xe8, 0xe0, 0x87, 0xe8, 0x58, 0x9c, + 0x9c, 0x44, 0x9a, 0x41, 0x3f, 0x86, 0x24, 0x77, 0xad, 0xc4, 0x25, 0xe4, 0xf9, 0xfd, 0x7b, 0x7e, + 0x79, 0x82, 0xda, 0x03, 0x90, 0x31, 0x48, 0x1a, 0x30, 0x31, 0xa2, 0x53, 0x97, 0x8e, 0x27, 0x3c, + 0x9d, 0x91, 0x24, 0x85, 0x0c, 0xac, 0x1d, 0xc5, 0x91, 0x82, 0x23, 0x53, 0xb7, 0x6d, 0x0f, 0x61, + 0x08, 0x25, 0x45, 0x8b, 0x37, 0xa5, 0x6a, 0xef, 0xb2, 0x38, 0x12, 0x40, 0xcb, 0xa7, 0x86, 0x5a, + 0x7f, 0x42, 0xcb, 0x00, 0x45, 0xe1, 0x0d, 0x25, 0x39, 0x9d, 0x76, 0x03, 0x9e, 0xb1, 0x2e, 0x1d, + 0x40, 0x24, 0xaa, 0xd6, 0x3b, 0xb5, 0x46, 0x17, 0x28, 0x07, 0xc7, 0x46, 0xd6, 0x75, 0xd1, 0xae, + 0xcf, 0x52, 0x16, 0x4b, 0x9f, 0x8f, 0x27, 0x5c, 0x66, 0x4e, 0x1f, 0xed, 0x55, 0x50, 0x99, 0x80, + 0x90, 0xdc, 0x3a, 0x43, 0xb5, 0xa4, 0x44, 0x9a, 0xe6, 0xa1, 0x79, 0xb4, 0xed, 0xee, 0x93, 0xea, + 0xc7, 0x10, 0xa5, 0xf7, 0x1a, 0x8b, 0x8f, 0x8e, 0xf1, 0xfc, 0xf5, 0x72, 0x6c, 0xfa, 0xda, 0xe0, + 0x44, 0x3a, 0xd1, 0x63, 0xf7, 0x4c, 0x0c, 0xb8, 0x5e, 0x64, 0xb9, 0xa8, 0xce, 0xc2, 0x30, 0xe5, + 0x52, 0x45, 0x36, 0xbc, 0xe6, 0xdb, 0xeb, 0x89, 0xad, 0x53, 0x2f, 0x14, 0x73, 0x93, 0xa5, 0x91, + 0x18, 0xfa, 0x6b, 0xa1, 0x65, 0xa3, 0xff, 0x21, 0x17, 0x10, 0x37, 0xff, 0x15, 0x0e, 0x5f, 0x0d, + 0xe7, 0x5b, 0x8f, 0xf3, 0x8e, 0xf1, 0x3d, 0xef, 0x18, 0xce, 0x15, 0xb2, 0xab, 0xab, 0x74, 0xfb, + 0x1e, 0xaa, 0x07, 0x0a, 0xd2, 0xf5, 0x5b, 0xbf, 0xf5, 0x25, 0x27, 0xfa, 0x6e, 0xe4, 0x12, 0x22, + 0xe1, 0xaf, 0x95, 0xde, 0xe9, 0x62, 0x85, 0xcd, 0xe5, 0x0a, 0x9b, 0x9f, 0x2b, 0x6c, 0x3e, 0xe5, + 0xd8, 0x58, 0xe6, 0xd8, 0x78, 0xcf, 0xb1, 0x71, 0x7b, 0xa0, 0xcc, 0x32, 0x1c, 0x91, 0x08, 0xe8, + 0xc3, 0xe6, 0xbf, 0x64, 0xb3, 0x84, 0xcb, 0xa0, 0x56, 0x9e, 0xb7, 0xf7, 0x13, 0x00, 0x00, 0xff, + 0xff, 0x4a, 0x63, 0x62, 0x68, 0x0b, 0x02, 0x00, 0x00, } func (m *QueryParamsRequest) Marshal() (dAtA []byte, err error) { @@ -188,6 +287,78 @@ func (m *QueryParamsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +func (m *QueryBalanceRequest) 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 *QueryBalanceRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryBalanceRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Denom) > 0 { + i -= len(m.Denom) + copy(dAtA[i:], m.Denom) + i = encodeVarintQuery(dAtA, i, uint64(len(m.Denom))) + i-- + dAtA[i] = 0x12 + } + if len(m.Address) > 0 { + i -= len(m.Address) + copy(dAtA[i:], m.Address) + i = encodeVarintQuery(dAtA, i, uint64(len(m.Address))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *QueryBalanceResponse) 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 *QueryBalanceResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryBalanceResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Balance != nil { + { + size, err := m.Balance.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 @@ -219,6 +390,36 @@ func (m *QueryParamsResponse) Size() (n int) { return n } +func (m *QueryBalanceRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Address) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + l = len(m.Denom) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryBalanceResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Balance != nil { + l = m.Balance.Size() + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + func sovQuery(x uint64) (n int) { return (math_bits.Len64(x|1) + 6) / 7 } @@ -358,6 +559,206 @@ func (m *QueryParamsResponse) Unmarshal(dAtA []byte) error { } return nil } +func (m *QueryBalanceRequest) 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: QueryBalanceRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryBalanceRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Address", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Address = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Denom", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Denom = string(dAtA[iNdEx:postIndex]) + 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 *QueryBalanceResponse) 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: QueryBalanceResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryBalanceResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Balance", 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.Balance == nil { + m.Balance = &types.Coin{} + } + if err := m.Balance.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/bank/v2/types/restrictions.go b/x/bank/v2/types/restrictions.go new file mode 100644 index 000000000000..89c1f7e6cfea --- /dev/null +++ b/x/bank/v2/types/restrictions.go @@ -0,0 +1,57 @@ +package types + +import ( + "context" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// A SendRestrictionFn can restrict sends and/or provide a new receiver address. +type SendRestrictionFn func(ctx context.Context, fromAddr, toAddr []byte, amt sdk.Coins) (newToAddr []byte, err error) + +// IsOnePerModuleType implements the depinject.OnePerModuleType interface. +func (SendRestrictionFn) IsOnePerModuleType() {} + +var _ SendRestrictionFn = NoOpSendRestrictionFn + +// NoOpSendRestrictionFn is a no-op SendRestrictionFn. +func NoOpSendRestrictionFn(_ context.Context, _, toAddr []byte, _ sdk.Coins) ([]byte, error) { + return toAddr, nil +} + +// Then creates a composite restriction that runs this one then the provided second one. +func (r SendRestrictionFn) Then(second SendRestrictionFn) SendRestrictionFn { + return ComposeSendRestrictions(r, second) +} + +// ComposeSendRestrictions combines multiple SendRestrictionFn into one. +// nil entries are ignored. +// If all entries are nil, nil is returned. +// If exactly one entry is not nil, it is returned. +// Otherwise, a new SendRestrictionFn is returned that runs the non-nil restrictions in the order they are given. +// The composition runs each send restriction until an error is encountered and returns that error, +// otherwise it returns the toAddr of the last send restriction. +func ComposeSendRestrictions(restrictions ...SendRestrictionFn) SendRestrictionFn { + toRun := make([]SendRestrictionFn, 0, len(restrictions)) + for _, r := range restrictions { + if r != nil { + toRun = append(toRun, r) + } + } + switch len(toRun) { + case 0: + return nil + case 1: + return toRun[0] + } + return func(ctx context.Context, fromAddr, toAddr []byte, amt sdk.Coins) ([]byte, error) { + var err error + for _, r := range toRun { + toAddr, err = r(ctx, fromAddr, toAddr, amt) + if err != nil { + return toAddr, err + } + } + return toAddr, err + } +} diff --git a/x/bank/v2/types/tx.pb.go b/x/bank/v2/types/tx.pb.go index 95736d2a721c..3867bdf64c84 100644 --- a/x/bank/v2/types/tx.pb.go +++ b/x/bank/v2/types/tx.pb.go @@ -6,6 +6,8 @@ package types import ( fmt "fmt" _ "github.com/cosmos/cosmos-proto" + github_com_cosmos_cosmos_sdk_types "github.com/cosmos/cosmos-sdk/types" + types "github.com/cosmos/cosmos-sdk/types" _ "github.com/cosmos/cosmos-sdk/types/msgservice" _ "github.com/cosmos/cosmos-sdk/types/tx/amino" _ "github.com/cosmos/gogoproto/gogoproto" @@ -119,34 +121,247 @@ func (m *MsgUpdateParamsResponse) XXX_DiscardUnknown() { var xxx_messageInfo_MsgUpdateParamsResponse proto.InternalMessageInfo +// MsgSend represents a message to send coins from one account to another. +type MsgSend 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"` +} + +func (m *MsgSend) Reset() { *m = MsgSend{} } +func (m *MsgSend) String() string { return proto.CompactTextString(m) } +func (*MsgSend) ProtoMessage() {} +func (*MsgSend) Descriptor() ([]byte, []int) { + return fileDescriptor_14123aa47d73c00a, []int{2} +} +func (m *MsgSend) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgSend) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgSend.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 *MsgSend) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgSend.Merge(m, src) +} +func (m *MsgSend) XXX_Size() int { + return m.Size() +} +func (m *MsgSend) XXX_DiscardUnknown() { + xxx_messageInfo_MsgSend.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgSend proto.InternalMessageInfo + +func (m *MsgSend) GetFromAddress() string { + if m != nil { + return m.FromAddress + } + return "" +} + +func (m *MsgSend) GetToAddress() string { + if m != nil { + return m.ToAddress + } + return "" +} + +func (m *MsgSend) GetAmount() github_com_cosmos_cosmos_sdk_types.Coins { + if m != nil { + return m.Amount + } + return nil +} + +// MsgSendResponse defines the response structure for executing a MsgSend message. +type MsgSendResponse struct { +} + +func (m *MsgSendResponse) Reset() { *m = MsgSendResponse{} } +func (m *MsgSendResponse) String() string { return proto.CompactTextString(m) } +func (*MsgSendResponse) ProtoMessage() {} +func (*MsgSendResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_14123aa47d73c00a, []int{3} +} +func (m *MsgSendResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgSendResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgSendResponse.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 *MsgSendResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgSendResponse.Merge(m, src) +} +func (m *MsgSendResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgSendResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgSendResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgSendResponse proto.InternalMessageInfo + +// MsgMint is the Msg/Mint request type. +type MsgMint struct { + // authority is the address that controls the module (defaults to x/gov unless overwritten). + Authority string `protobuf:"bytes,1,opt,name=authority,proto3" json:"authority,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"` +} + +func (m *MsgMint) Reset() { *m = MsgMint{} } +func (m *MsgMint) String() string { return proto.CompactTextString(m) } +func (*MsgMint) ProtoMessage() {} +func (*MsgMint) Descriptor() ([]byte, []int) { + return fileDescriptor_14123aa47d73c00a, []int{4} +} +func (m *MsgMint) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgMint) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgMint.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 *MsgMint) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgMint.Merge(m, src) +} +func (m *MsgMint) XXX_Size() int { + return m.Size() +} +func (m *MsgMint) XXX_DiscardUnknown() { + xxx_messageInfo_MsgMint.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgMint proto.InternalMessageInfo + +func (m *MsgMint) GetAuthority() string { + if m != nil { + return m.Authority + } + return "" +} + +func (m *MsgMint) GetToAddress() string { + if m != nil { + return m.ToAddress + } + return "" +} + +func (m *MsgMint) GetAmount() github_com_cosmos_cosmos_sdk_types.Coins { + if m != nil { + return m.Amount + } + return nil +} + +// MsgMint defines the response structure for executing a MsgMint message. +type MsgMintResponse struct { +} + +func (m *MsgMintResponse) Reset() { *m = MsgMintResponse{} } +func (m *MsgMintResponse) String() string { return proto.CompactTextString(m) } +func (*MsgMintResponse) ProtoMessage() {} +func (*MsgMintResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_14123aa47d73c00a, []int{5} +} +func (m *MsgMintResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgMintResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgMintResponse.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 *MsgMintResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgMintResponse.Merge(m, src) +} +func (m *MsgMintResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgMintResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgMintResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgMintResponse proto.InternalMessageInfo + func init() { proto.RegisterType((*MsgUpdateParams)(nil), "cosmos.bank.v2.MsgUpdateParams") proto.RegisterType((*MsgUpdateParamsResponse)(nil), "cosmos.bank.v2.MsgUpdateParamsResponse") + proto.RegisterType((*MsgSend)(nil), "cosmos.bank.v2.MsgSend") + proto.RegisterType((*MsgSendResponse)(nil), "cosmos.bank.v2.MsgSendResponse") + proto.RegisterType((*MsgMint)(nil), "cosmos.bank.v2.MsgMint") + proto.RegisterType((*MsgMintResponse)(nil), "cosmos.bank.v2.MsgMintResponse") } func init() { proto.RegisterFile("cosmos/bank/v2/tx.proto", fileDescriptor_14123aa47d73c00a) } var fileDescriptor_14123aa47d73c00a = []byte{ - // 299 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0x4f, 0xce, 0x2f, 0xce, - 0xcd, 0x2f, 0xd6, 0x4f, 0x4a, 0xcc, 0xcb, 0xd6, 0x2f, 0x33, 0xd2, 0x2f, 0xa9, 0xd0, 0x2b, 0x28, - 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x83, 0x48, 0xe8, 0x81, 0x24, 0xf4, 0xca, 0x8c, 0xa4, 0x44, 0xd2, - 0xf3, 0xd3, 0xf3, 0xc1, 0x52, 0xfa, 0x20, 0x16, 0x44, 0x95, 0x94, 0x24, 0x9a, 0x76, 0xb0, 0x6a, - 0x14, 0xa9, 0x78, 0x88, 0x1e, 0xa8, 0x69, 0x10, 0x29, 0x98, 0xa5, 0xb9, 0xc5, 0xe9, 0xfa, 0x65, - 0x86, 0x20, 0x0a, 0x2a, 0x21, 0x98, 0x98, 0x9b, 0x99, 0x97, 0xaf, 0x0f, 0x26, 0x21, 0x42, 0x4a, - 0x7b, 0x19, 0xb9, 0xf8, 0x7d, 0x8b, 0xd3, 0x43, 0x0b, 0x52, 0x12, 0x4b, 0x52, 0x03, 0x12, 0x8b, - 0x12, 0x73, 0x8b, 0x85, 0xcc, 0xb8, 0x38, 0x13, 0x4b, 0x4b, 0x32, 0xf2, 0x8b, 0x32, 0x4b, 0x2a, - 0x25, 0x18, 0x15, 0x18, 0x35, 0x38, 0x9d, 0x24, 0x2e, 0x6d, 0xd1, 0x15, 0x81, 0x5a, 0xe2, 0x98, - 0x92, 0x52, 0x94, 0x5a, 0x5c, 0x1c, 0x5c, 0x52, 0x94, 0x99, 0x97, 0x1e, 0x84, 0x50, 0x2a, 0x64, - 0xc9, 0xc5, 0x56, 0x00, 0x36, 0x41, 0x82, 0x49, 0x81, 0x51, 0x83, 0xdb, 0x48, 0x4c, 0x0f, 0xd5, - 0x93, 0x7a, 0x10, 0xf3, 0x9d, 0x38, 0x4f, 0xdc, 0x93, 0x67, 0x58, 0xf1, 0x7c, 0x83, 0x16, 0x63, - 0x10, 0x54, 0x83, 0x95, 0x79, 0xd3, 0xf3, 0x0d, 0x5a, 0x08, 0xa3, 0xba, 0x9e, 0x6f, 0xd0, 0x52, - 0x81, 0x68, 0xd6, 0x2d, 0x4e, 0xc9, 0xd6, 0xaf, 0x80, 0x87, 0x00, 0x9a, 0x5b, 0x95, 0x24, 0xb9, - 0xc4, 0xd1, 0x84, 0x82, 0x52, 0x8b, 0x0b, 0xf2, 0xf3, 0x8a, 0x53, 0x9d, 0xcc, 0x4e, 0x3c, 0x92, - 0x63, 0xbc, 0xf0, 0x48, 0x8e, 0xf1, 0xc1, 0x23, 0x39, 0xc6, 0x09, 0x8f, 0xe5, 0x18, 0x2e, 0x3c, - 0x96, 0x63, 0xb8, 0xf1, 0x58, 0x8e, 0x21, 0x4a, 0x06, 0x62, 0x74, 0x71, 0x4a, 0xb6, 0x5e, 0x66, - 0x3e, 0x92, 0xe1, 0x25, 0x95, 0x05, 0xa9, 0xc5, 0x49, 0x6c, 0xe0, 0x90, 0x31, 0x06, 0x04, 0x00, - 0x00, 0xff, 0xff, 0xbd, 0xd0, 0xd5, 0x76, 0xbc, 0x01, 0x00, 0x00, + // 492 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x93, 0xb1, 0x8b, 0x13, 0x41, + 0x14, 0xc6, 0xb3, 0x39, 0x88, 0x64, 0x72, 0x28, 0xb7, 0x1c, 0x5e, 0x72, 0xc8, 0x5e, 0x08, 0x16, + 0x21, 0x70, 0x33, 0x64, 0x85, 0x3b, 0x3c, 0x2b, 0x23, 0xd8, 0x05, 0x24, 0x87, 0x8d, 0x4d, 0x98, + 0x64, 0xc7, 0xbd, 0x25, 0xee, 0xbc, 0x65, 0xdf, 0x24, 0x5c, 0x5a, 0x4b, 0x2b, 0x6b, 0xff, 0x00, + 0x11, 0x0b, 0x49, 0x61, 0x6b, 0x7f, 0xe5, 0x61, 0x65, 0xa5, 0x92, 0x14, 0xf9, 0x37, 0x64, 0x76, + 0x26, 0xc9, 0x25, 0x72, 0x04, 0xec, 0x6c, 0x92, 0x61, 0xbe, 0xf7, 0x7d, 0xf3, 0xe6, 0x37, 0x6f, + 0xc9, 0x41, 0x1f, 0x30, 0x06, 0x64, 0x3d, 0x2e, 0x07, 0x6c, 0xe4, 0x33, 0x75, 0x49, 0x93, 0x14, + 0x14, 0xb8, 0x77, 0x8d, 0x40, 0xb5, 0x40, 0x47, 0xfe, 0xe1, 0x7e, 0x08, 0x21, 0x64, 0x12, 0xd3, + 0x2b, 0x53, 0x75, 0x58, 0xd9, 0xb0, 0x67, 0xd5, 0x6b, 0x52, 0xd7, 0x78, 0x6c, 0x9a, 0x91, 0x16, + 0x87, 0xc6, 0x18, 0xb2, 0x51, 0x53, 0xff, 0x59, 0x61, 0x8f, 0xc7, 0x91, 0x04, 0x96, 0xfd, 0xda, + 0x2d, 0x6f, 0x79, 0x02, 0x0a, 0x36, 0x6a, 0xf6, 0x84, 0xe2, 0x4d, 0xd6, 0x87, 0x48, 0x1a, 0xbd, + 0xf6, 0xcd, 0x21, 0xf7, 0xda, 0x18, 0xbe, 0x4c, 0x02, 0xae, 0xc4, 0x0b, 0x9e, 0xf2, 0x18, 0xdd, + 0x13, 0x52, 0xe4, 0x43, 0x75, 0x01, 0x69, 0xa4, 0xc6, 0x65, 0xa7, 0xea, 0xd4, 0x8b, 0xad, 0xf2, + 0xf7, 0xaf, 0xc7, 0xfb, 0xb6, 0x89, 0xa7, 0x41, 0x90, 0x0a, 0xc4, 0x73, 0x95, 0x46, 0x32, 0xec, + 0xac, 0x4a, 0xdd, 0xc7, 0xa4, 0x90, 0x64, 0x09, 0xe5, 0x7c, 0xd5, 0xa9, 0x97, 0xfc, 0xfb, 0x74, + 0x1d, 0x02, 0x35, 0xf9, 0xad, 0xe2, 0xd5, 0xcf, 0xa3, 0xdc, 0xa7, 0xf9, 0xa4, 0xe1, 0x74, 0xac, + 0xe1, 0xec, 0xf4, 0xed, 0x7c, 0xd2, 0x58, 0x45, 0xbd, 0x9b, 0x4f, 0x1a, 0x0f, 0x8d, 0xf9, 0x18, + 0x83, 0x01, 0xbb, 0x5c, 0x12, 0xda, 0xe8, 0xb5, 0x56, 0x21, 0x07, 0x1b, 0x5b, 0x1d, 0x81, 0x09, + 0x48, 0x14, 0xb5, 0x2f, 0x79, 0x72, 0xa7, 0x8d, 0xe1, 0xb9, 0x90, 0x81, 0xfb, 0x84, 0xec, 0xbe, + 0x4e, 0x21, 0xee, 0x72, 0xd3, 0xfb, 0xd6, 0x5b, 0x95, 0x74, 0xb5, 0xdd, 0x72, 0x4f, 0x09, 0x51, + 0xb0, 0xb4, 0xe6, 0xb7, 0x01, 0x51, 0xb0, 0x30, 0x8e, 0x49, 0x81, 0xc7, 0x30, 0x94, 0xaa, 0xbc, + 0x53, 0xdd, 0xa9, 0x97, 0xfc, 0xca, 0x0a, 0x08, 0x0a, 0x6a, 0x5f, 0x83, 0x3e, 0x83, 0x48, 0xb6, + 0x9e, 0x6b, 0x26, 0x9f, 0x7f, 0x1d, 0xd5, 0xc3, 0x48, 0x5d, 0x0c, 0x7b, 0xb4, 0x0f, 0xb1, 0x7d, + 0x74, 0x76, 0x83, 0x83, 0x1a, 0x27, 0x02, 0x33, 0x03, 0x7e, 0x98, 0x4f, 0x1a, 0xbb, 0x6f, 0x44, + 0xc8, 0xfb, 0xe3, 0xae, 0x7e, 0x4f, 0xb4, 0x40, 0xcd, 0x81, 0x67, 0xbe, 0x06, 0xba, 0x76, 0x67, + 0xcd, 0xf4, 0xc1, 0x6d, 0x4c, 0x35, 0xa4, 0xda, 0x5e, 0x36, 0x0a, 0x7a, 0xb9, 0x64, 0xf8, 0xd1, + 0x30, 0x6c, 0x47, 0x52, 0xfd, 0xf3, 0x58, 0xfc, 0x8f, 0xf8, 0xd8, 0xdf, 0xf3, 0x78, 0x2b, 0x3b, + 0x0d, 0xc7, 0xb2, 0xd3, 0xcb, 0x05, 0xbb, 0xd6, 0xc9, 0xd5, 0xd4, 0x73, 0xae, 0xa7, 0x9e, 0xf3, + 0x7b, 0xea, 0x39, 0xef, 0x67, 0x5e, 0xee, 0x7a, 0xe6, 0xe5, 0x7e, 0xcc, 0xbc, 0xdc, 0x2b, 0x1b, + 0x85, 0xc1, 0x80, 0x46, 0x70, 0x23, 0x2c, 0xeb, 0xaf, 0x57, 0xc8, 0xbe, 0xcc, 0x47, 0x7f, 0x02, + 0x00, 0x00, 0xff, 0xff, 0x9a, 0xff, 0x7c, 0x62, 0x5c, 0x04, 0x00, 0x00, } func (m *MsgUpdateParams) Marshal() (dAtA []byte, err error) { @@ -212,48 +427,623 @@ func (m *MsgUpdateParamsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) return len(dAtA) - i, nil } -func encodeVarintTx(dAtA []byte, offset int, v uint64) int { - offset -= sovTx(v) - base := offset - for v >= 1<<7 { - dAtA[offset] = uint8(v&0x7f | 0x80) - v >>= 7 - offset++ +func (m *MsgSend) 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 *MsgSend) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgSend) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Amount) > 0 { + for iNdEx := len(m.Amount) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Amount[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTx(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + } + if len(m.ToAddress) > 0 { + i -= len(m.ToAddress) + copy(dAtA[i:], m.ToAddress) + i = encodeVarintTx(dAtA, i, uint64(len(m.ToAddress))) + i-- + dAtA[i] = 0x12 + } + if len(m.FromAddress) > 0 { + i -= len(m.FromAddress) + copy(dAtA[i:], m.FromAddress) + i = encodeVarintTx(dAtA, i, uint64(len(m.FromAddress))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MsgSendResponse) 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 *MsgSendResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgSendResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *MsgMint) 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 *MsgMint) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgMint) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Amount) > 0 { + for iNdEx := len(m.Amount) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Amount[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTx(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + } + if len(m.ToAddress) > 0 { + i -= len(m.ToAddress) + copy(dAtA[i:], m.ToAddress) + i = encodeVarintTx(dAtA, i, uint64(len(m.ToAddress))) + i-- + dAtA[i] = 0x12 + } + if len(m.Authority) > 0 { + i -= len(m.Authority) + copy(dAtA[i:], m.Authority) + i = encodeVarintTx(dAtA, i, uint64(len(m.Authority))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MsgMintResponse) 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 *MsgMintResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgMintResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func encodeVarintTx(dAtA []byte, offset int, v uint64) int { + offset -= sovTx(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *MsgUpdateParams) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Authority) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = m.Params.Size() + n += 1 + l + sovTx(uint64(l)) + return n +} + +func (m *MsgUpdateParamsResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *MsgSend) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.FromAddress) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.ToAddress) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + if len(m.Amount) > 0 { + for _, e := range m.Amount { + l = e.Size() + n += 1 + l + sovTx(uint64(l)) + } + } + return n +} + +func (m *MsgSendResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *MsgMint) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Authority) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.ToAddress) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + if len(m.Amount) > 0 { + for _, e := range m.Amount { + l = e.Size() + n += 1 + l + sovTx(uint64(l)) + } + } + return n +} + +func (m *MsgMintResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func sovTx(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozTx(x uint64) (n int) { + return sovTx(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *MsgUpdateParams) 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 ErrIntOverflowTx + } + 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: MsgUpdateParams: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgUpdateParams: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Authority", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Authority = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Params", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Params.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgUpdateParamsResponse) 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 ErrIntOverflowTx + } + 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: MsgUpdateParamsResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgUpdateParamsResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF } - dAtA[offset] = uint8(v) - return base + return nil } -func (m *MsgUpdateParams) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.Authority) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) +func (m *MsgSend) 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 ErrIntOverflowTx + } + 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: MsgSend: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgSend: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field FromAddress", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.FromAddress = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ToAddress", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ToAddress = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Amount", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Amount = append(m.Amount, types.Coin{}) + if err := m.Amount[len(m.Amount)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } } - l = m.Params.Size() - n += 1 + l + sovTx(uint64(l)) - return n -} -func (m *MsgUpdateParamsResponse) Size() (n int) { - if m == nil { - return 0 + if iNdEx > l { + return io.ErrUnexpectedEOF } - var l int - _ = l - return n + return nil } +func (m *MsgSendResponse) 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 ErrIntOverflowTx + } + 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: MsgSendResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgSendResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } -func sovTx(x uint64) (n int) { - return (math_bits.Len64(x|1) + 6) / 7 -} -func sozTx(x uint64) (n int) { - return sovTx(uint64((x << 1) ^ uint64((int64(x) >> 63)))) + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil } -func (m *MsgUpdateParams) Unmarshal(dAtA []byte) error { +func (m *MsgMint) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -276,10 +1066,10 @@ func (m *MsgUpdateParams) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: MsgUpdateParams: wiretype end group for non-group") + return fmt.Errorf("proto: MsgMint: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: MsgUpdateParams: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: MsgMint: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: @@ -316,7 +1106,39 @@ func (m *MsgUpdateParams) Unmarshal(dAtA []byte) error { iNdEx = postIndex case 2: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Params", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field ToAddress", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ToAddress = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Amount", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -343,7 +1165,8 @@ func (m *MsgUpdateParams) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if err := m.Params.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + m.Amount = append(m.Amount, types.Coin{}) + if err := m.Amount[len(m.Amount)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex @@ -368,7 +1191,7 @@ func (m *MsgUpdateParams) Unmarshal(dAtA []byte) error { } return nil } -func (m *MsgUpdateParamsResponse) Unmarshal(dAtA []byte) error { +func (m *MsgMintResponse) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -391,10 +1214,10 @@ func (m *MsgUpdateParamsResponse) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: MsgUpdateParamsResponse: wiretype end group for non-group") + return fmt.Errorf("proto: MsgMintResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: MsgUpdateParamsResponse: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: MsgMintResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { default: diff --git a/x/circuit/autocli.go b/x/circuit/autocli.go index e9055caf5185..e9cc67701cf7 100644 --- a/x/circuit/autocli.go +++ b/x/circuit/autocli.go @@ -43,7 +43,7 @@ func (am AppModule) AutoCLIOptions() *autocliv1.ModuleOptions { "SOME_MSGS" = 1, "ALL_MSGS" = 2, "SUPER_ADMIN" = 3,`, - Example: fmt.Sprintf(`%s circuit authorize [address] '{"level":1,"limit_type_urls":["cosmos.bank.v1beta1.MsgSend,cosmos.bank.v1beta1.MsgMultiSend"]}'"`, version.AppName), + Example: fmt.Sprintf(`%s tx circuit authorize [address] '{"level":1,"limit_type_urls":["/cosmos.bank.v1beta1.MsgSend, /cosmos.bank.v1beta1.MsgMultiSend"]}'"`, version.AppName), PositionalArgs: []*autocliv1.PositionalArgDescriptor{ {ProtoField: "grantee"}, {ProtoField: "permissions"}, // TODO(@julienrbrt) Support flattening msg for setting each field as a positional arg @@ -53,7 +53,7 @@ func (am AppModule) AutoCLIOptions() *autocliv1.ModuleOptions { RpcMethod: "TripCircuitBreaker", Use: "disable ", Short: "Disable a message from being executed", - Example: fmt.Sprintf(`%s circuit disable "cosmos.bank.v1beta1.MsgSend cosmos.bank.v1beta1.MsgMultiSend"`, version.AppName), + Example: fmt.Sprintf(`%s tx circuit disable "/cosmos.bank.v1beta1.MsgSend /cosmos.bank.v1beta1.MsgMultiSend"`, version.AppName), PositionalArgs: []*autocliv1.PositionalArgDescriptor{ {ProtoField: "msg_type_urls", Varargs: true}, }, @@ -62,7 +62,7 @@ func (am AppModule) AutoCLIOptions() *autocliv1.ModuleOptions { RpcMethod: "ResetCircuitBreaker", Use: "reset ", Short: "Enable a message to be executed", - Example: fmt.Sprintf(`%s circuit reset "cosmos.bank.v1beta1.MsgSend cosmos.bank.v1beta1.MsgMultiSend"`, version.AppName), + Example: fmt.Sprintf(`%s tx circuit reset "/cosmos.bank.v1beta1.MsgSend /cosmos.bank.v1beta1.MsgMultiSend"`, version.AppName), PositionalArgs: []*autocliv1.PositionalArgDescriptor{ {ProtoField: "msg_type_urls", Varargs: true}, }, diff --git a/x/circuit/go.mod b/x/circuit/go.mod index c35b3e0e5469..57801be443d0 100644 --- a/x/circuit/go.mod +++ b/x/circuit/go.mod @@ -3,10 +3,10 @@ module cosmossdk.io/x/circuit go 1.23.1 require ( - cosmossdk.io/api v0.7.5 + cosmossdk.io/api v0.7.6 cosmossdk.io/collections v0.4.0 - cosmossdk.io/core v1.0.0-alpha.2 - cosmossdk.io/core/testing v0.0.0-00010101000000-000000000000 + cosmossdk.io/core v1.0.0-alpha.4 + cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29 cosmossdk.io/depinject v1.0.0 cosmossdk.io/errors v1.0.1 cosmossdk.io/store v1.1.1-0.20240418092142-896cdf1971bc @@ -15,8 +15,8 @@ require ( github.com/golang/protobuf v1.5.4 github.com/grpc-ecosystem/grpc-gateway v1.16.0 github.com/stretchr/testify v1.9.0 - google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 - google.golang.org/grpc v1.66.2 + google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 + google.golang.org/grpc v1.67.1 ) require ( @@ -24,7 +24,7 @@ require ( buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.34.2-20240130113600-88ef6483f90f.2 // indirect cosmossdk.io/log v1.4.1 // indirect cosmossdk.io/math v1.3.0 // indirect - cosmossdk.io/schema v0.2.0 // indirect + cosmossdk.io/schema v0.3.1-0.20240930054013-7c6e0388a3f9 // indirect cosmossdk.io/x/bank v0.0.0-20240226161501-23359a0b6d91 // indirect cosmossdk.io/x/staking v0.0.0-00010101000000-000000000000 // indirect cosmossdk.io/x/tx v0.13.3 // indirect @@ -96,7 +96,7 @@ require ( github.com/hashicorp/hcl v1.0.0 // indirect github.com/hashicorp/yamux v0.1.1 // indirect github.com/hdevalence/ed25519consensus v0.2.0 // indirect - github.com/huandu/skiplist v1.2.0 // indirect + github.com/huandu/skiplist v1.2.1 // indirect github.com/iancoleman/strcase v0.3.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jmhodges/levigo v1.0.0 // indirect @@ -119,9 +119,9 @@ require ( github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/client_golang v1.20.3 // indirect + github.com/prometheus/client_golang v1.20.4 // indirect github.com/prometheus/client_model v0.6.1 // indirect - github.com/prometheus/common v0.59.1 // indirect + github.com/prometheus/common v0.60.0 // indirect github.com/prometheus/procfs v0.15.1 // indirect github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect github.com/rogpeppe/go-internal v1.12.0 // indirect @@ -158,7 +158,7 @@ require ( golang.org/x/text v0.18.0 // indirect golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f // indirect google.golang.org/protobuf v1.34.2 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect @@ -172,7 +172,6 @@ replace github.com/cosmos/cosmos-sdk => ../../. // TODO remove post spinning out all modules replace ( cosmossdk.io/api => ../../api - cosmossdk.io/core/testing => ../../core/testing cosmossdk.io/store => ../../store cosmossdk.io/x/bank => ../bank cosmossdk.io/x/staking => ../staking diff --git a/x/circuit/go.sum b/x/circuit/go.sum index a658644fd79f..c9df997e10ec 100644 --- a/x/circuit/go.sum +++ b/x/circuit/go.sum @@ -6,8 +6,10 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cosmossdk.io/collections v0.4.0 h1:PFmwj2W8szgpD5nOd8GWH6AbYNi1f2J6akWXJ7P5t9s= cosmossdk.io/collections v0.4.0/go.mod h1:oa5lUING2dP+gdDquow+QjlF45eL1t4TJDypgGd+tv0= -cosmossdk.io/core v1.0.0-alpha.2 h1:epU0Xwces4Rgl5bMhHHkXGaGDcyucNGlC/JDH+Suckg= -cosmossdk.io/core v1.0.0-alpha.2/go.mod h1:abgLjeFLhtuKIYZWSPlVUgQBrKObO7ULV35KYfexE90= +cosmossdk.io/core v1.0.0-alpha.4 h1:9iuroT9ejDYETCsGkzkvs/wAY/5UFl7nCIINFRxyMJY= +cosmossdk.io/core v1.0.0-alpha.4/go.mod h1:3u9cWq1FAVtiiCrDPpo4LhR+9V6k/ycSG4/Y/tREWCY= +cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29 h1:NxxUo0GMJUbIuVg0R70e3cbn9eFTEuMr7ev1AFvypdY= +cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29/go.mod h1:8s2tPeJtSiQuoyPmr2Ag7meikonISO4Fv4MoO8+ORrs= cosmossdk.io/depinject v1.0.0 h1:dQaTu6+O6askNXO06+jyeUAnF2/ssKwrrszP9t5q050= cosmossdk.io/depinject v1.0.0/go.mod h1:zxK/h3HgHoA/eJVtiSsoaRaRA2D5U4cJ5thIG4ssbB8= cosmossdk.io/errors v1.0.1 h1:bzu+Kcr0kS/1DuPBtUFdWjzLqyUuCiyHjyJB6srBV/0= @@ -16,8 +18,8 @@ cosmossdk.io/log v1.4.1 h1:wKdjfDRbDyZRuWa8M+9nuvpVYxrEOwbD/CA8hvhU8QM= cosmossdk.io/log v1.4.1/go.mod h1:k08v0Pyq+gCP6phvdI6RCGhLf/r425UT6Rk/m+o74rU= cosmossdk.io/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE= cosmossdk.io/math v1.3.0/go.mod h1:vnRTxewy+M7BtXBNFybkuhSH4WfedVAAnERHgVFhp3k= -cosmossdk.io/schema v0.2.0 h1:UH5CR1DqUq8yP+5Np8PbvG4YX0zAUsTN2Qk6yThmfMk= -cosmossdk.io/schema v0.2.0/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= +cosmossdk.io/schema v0.3.1-0.20240930054013-7c6e0388a3f9 h1:DmOoS/1PeY6Ih0hAVlJ69kLMUrLV+TCbfICrZtB1vdU= +cosmossdk.io/schema v0.3.1-0.20240930054013-7c6e0388a3f9/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMbk2FiG/kXiLl8BRyzTWDw7gX/Hz7Dd5eDMs= @@ -292,8 +294,8 @@ github.com/hdevalence/ed25519consensus v0.2.0/go.mod h1:w3BHWjwJbFU29IRHL1Iqkw3s github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/huandu/go-assert v1.1.5 h1:fjemmA7sSfYHJD7CUqs9qTwwfdNAx7/j2/ZlHXzNB3c= github.com/huandu/go-assert v1.1.5/go.mod h1:yOLvuqZwmcHIC5rIzrBhT7D3Q9c3GFnd0JrPVhn/06U= -github.com/huandu/skiplist v1.2.0 h1:gox56QD77HzSC0w+Ws3MH3iie755GBJU1OER3h5VsYw= -github.com/huandu/skiplist v1.2.0/go.mod h1:7v3iFjLcSAzO4fN5B8dvebvo/qsfumiLiDXMrPiHF9w= +github.com/huandu/skiplist v1.2.1 h1:dTi93MgjwErA/8idWTzIw4Y1kZsMWx35fmI2c8Rij7w= +github.com/huandu/skiplist v1.2.1/go.mod h1:7v3iFjLcSAzO4fN5B8dvebvo/qsfumiLiDXMrPiHF9w= github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI= github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= @@ -402,8 +404,8 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= -github.com/prometheus/client_golang v1.20.3 h1:oPksm4K8B+Vt35tUhw6GbSNSgVlVSBH0qELP/7u83l4= -github.com/prometheus/client_golang v1.20.3/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_golang v1.20.4 h1:Tgh3Yr67PaOv/uTqloMsCEdeuFTatm5zIq5+qNN23vI= +github.com/prometheus/client_golang v1.20.4/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -412,8 +414,8 @@ github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= -github.com/prometheus/common v0.59.1 h1:LXb1quJHWm1P6wq/U824uxYi4Sg0oGvNeUm1z5dJoX0= -github.com/prometheus/common v0.59.1/go.mod h1:GpWM7dewqmVYcd7SmRaiWVe9SSqjf0UrwnYnpEZNuT0= +github.com/prometheus/common v0.60.0 h1:+V9PAREWNvJMAuJ1x1BaWl9dewMW4YrHZQbx0sJNllA= +github.com/prometheus/common v0.60.0/go.mod h1:h0LYf1R1deLSKtD4Vdg8gy4RuOvENW2J/h19V5NADQw= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/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= @@ -636,10 +638,10 @@ google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEY google.golang.org/genproto v0.0.0-20220314164441-57ef72a4c106/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E= google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de h1:F6qOa9AZTYJXOUEr4jDysRDLrm4PHePlge4v4TGAlxY= google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:VUhTRKeHn9wwcdrk73nvdC9gF178Tzhmt/qyaFcPLSo= -google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 h1:+rdxYoE3E5htTEWIe15GlN6IfvbURM//Jt0mmkmm6ZU= -google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117/go.mod h1:OimBR/bc1wPO9iV4NC2bpyjy3VnAwZh5EBPQdtaE5oo= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:pPJltXNxVzT4pK9yD8vR9X75DaWYYmLGMsEvBfFQZzQ= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= +google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 h1:wKguEg1hsxI2/L3hUYrpo1RVi48K+uTyzKqprwLXsb8= +google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142/go.mod h1:d6be+8HhtEtucleCbxpPW9PA9XwISACu8nvpPqF0BVo= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f h1:cUMEy+8oS78BWIH9OWazBkzbr090Od9tWBNtZHkOhf0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= @@ -650,8 +652,8 @@ google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= -google.golang.org/grpc v1.66.2 h1:3QdXkuq3Bkh7w+ywLdLvM56cmGvQHUMZpiCzt6Rqaoo= -google.golang.org/grpc v1.66.2/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y= +google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E= +google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= 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= diff --git a/x/consensus/go.mod b/x/consensus/go.mod index 108f006087a0..cee2372dc92d 100644 --- a/x/consensus/go.mod +++ b/x/consensus/go.mod @@ -3,10 +3,10 @@ module cosmossdk.io/x/consensus go 1.23.1 require ( - cosmossdk.io/api v0.7.5 + cosmossdk.io/api v0.7.6 cosmossdk.io/collections v0.4.0 - cosmossdk.io/core v1.0.0-alpha.2 - cosmossdk.io/core/testing v0.0.0-00010101000000-000000000000 + cosmossdk.io/core v1.0.0-alpha.4 + cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29 cosmossdk.io/depinject v1.0.0 cosmossdk.io/store v1.1.1-0.20240418092142-896cdf1971bc github.com/cometbft/cometbft v1.0.0-rc1.0.20240908111210-ab0be101882f @@ -17,8 +17,8 @@ require ( github.com/golang/protobuf v1.5.4 github.com/grpc-ecosystem/grpc-gateway v1.16.0 github.com/stretchr/testify v1.9.0 - google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 - google.golang.org/grpc v1.66.2 + google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 + google.golang.org/grpc v1.67.1 ) require ( @@ -27,7 +27,7 @@ require ( cosmossdk.io/errors v1.0.1 // indirect cosmossdk.io/log v1.4.1 // indirect cosmossdk.io/math v1.3.0 // indirect - cosmossdk.io/schema v0.2.0 // indirect + cosmossdk.io/schema v0.3.1-0.20240930054013-7c6e0388a3f9 // indirect cosmossdk.io/x/bank v0.0.0-20240226161501-23359a0b6d91 // indirect cosmossdk.io/x/staking v0.0.0-00010101000000-000000000000 // indirect cosmossdk.io/x/tx v0.13.3 // indirect @@ -95,7 +95,7 @@ require ( github.com/hashicorp/hcl v1.0.0 // indirect github.com/hashicorp/yamux v0.1.1 // indirect github.com/hdevalence/ed25519consensus v0.2.0 // indirect - github.com/huandu/skiplist v1.2.0 // indirect + github.com/huandu/skiplist v1.2.1 // indirect github.com/iancoleman/strcase v0.3.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jmhodges/levigo v1.0.0 // indirect @@ -118,9 +118,9 @@ require ( github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/client_golang v1.20.3 // indirect + github.com/prometheus/client_golang v1.20.4 // indirect github.com/prometheus/client_model v0.6.1 // indirect - github.com/prometheus/common v0.59.1 // indirect + github.com/prometheus/common v0.60.0 // indirect github.com/prometheus/procfs v0.15.1 // indirect github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect github.com/rogpeppe/go-internal v1.12.0 // indirect @@ -157,7 +157,7 @@ require ( golang.org/x/text v0.18.0 // indirect golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f // indirect google.golang.org/protobuf v1.34.2 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect @@ -170,7 +170,6 @@ replace github.com/cosmos/cosmos-sdk => ../../. replace ( cosmossdk.io/api => ../../api - cosmossdk.io/core/testing => ../../core/testing cosmossdk.io/store => ../../store cosmossdk.io/x/bank => ../bank cosmossdk.io/x/staking => ../staking diff --git a/x/consensus/go.sum b/x/consensus/go.sum index 27af6ac5b1b3..6a6b2df0b205 100644 --- a/x/consensus/go.sum +++ b/x/consensus/go.sum @@ -6,8 +6,10 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cosmossdk.io/collections v0.4.0 h1:PFmwj2W8szgpD5nOd8GWH6AbYNi1f2J6akWXJ7P5t9s= cosmossdk.io/collections v0.4.0/go.mod h1:oa5lUING2dP+gdDquow+QjlF45eL1t4TJDypgGd+tv0= -cosmossdk.io/core v1.0.0-alpha.2 h1:epU0Xwces4Rgl5bMhHHkXGaGDcyucNGlC/JDH+Suckg= -cosmossdk.io/core v1.0.0-alpha.2/go.mod h1:abgLjeFLhtuKIYZWSPlVUgQBrKObO7ULV35KYfexE90= +cosmossdk.io/core v1.0.0-alpha.4 h1:9iuroT9ejDYETCsGkzkvs/wAY/5UFl7nCIINFRxyMJY= +cosmossdk.io/core v1.0.0-alpha.4/go.mod h1:3u9cWq1FAVtiiCrDPpo4LhR+9V6k/ycSG4/Y/tREWCY= +cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29 h1:NxxUo0GMJUbIuVg0R70e3cbn9eFTEuMr7ev1AFvypdY= +cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29/go.mod h1:8s2tPeJtSiQuoyPmr2Ag7meikonISO4Fv4MoO8+ORrs= cosmossdk.io/depinject v1.0.0 h1:dQaTu6+O6askNXO06+jyeUAnF2/ssKwrrszP9t5q050= cosmossdk.io/depinject v1.0.0/go.mod h1:zxK/h3HgHoA/eJVtiSsoaRaRA2D5U4cJ5thIG4ssbB8= cosmossdk.io/errors v1.0.1 h1:bzu+Kcr0kS/1DuPBtUFdWjzLqyUuCiyHjyJB6srBV/0= @@ -16,8 +18,8 @@ cosmossdk.io/log v1.4.1 h1:wKdjfDRbDyZRuWa8M+9nuvpVYxrEOwbD/CA8hvhU8QM= cosmossdk.io/log v1.4.1/go.mod h1:k08v0Pyq+gCP6phvdI6RCGhLf/r425UT6Rk/m+o74rU= cosmossdk.io/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE= cosmossdk.io/math v1.3.0/go.mod h1:vnRTxewy+M7BtXBNFybkuhSH4WfedVAAnERHgVFhp3k= -cosmossdk.io/schema v0.2.0 h1:UH5CR1DqUq8yP+5Np8PbvG4YX0zAUsTN2Qk6yThmfMk= -cosmossdk.io/schema v0.2.0/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= +cosmossdk.io/schema v0.3.1-0.20240930054013-7c6e0388a3f9 h1:DmOoS/1PeY6Ih0hAVlJ69kLMUrLV+TCbfICrZtB1vdU= +cosmossdk.io/schema v0.3.1-0.20240930054013-7c6e0388a3f9/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMbk2FiG/kXiLl8BRyzTWDw7gX/Hz7Dd5eDMs= @@ -292,8 +294,8 @@ github.com/hdevalence/ed25519consensus v0.2.0/go.mod h1:w3BHWjwJbFU29IRHL1Iqkw3s github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/huandu/go-assert v1.1.5 h1:fjemmA7sSfYHJD7CUqs9qTwwfdNAx7/j2/ZlHXzNB3c= github.com/huandu/go-assert v1.1.5/go.mod h1:yOLvuqZwmcHIC5rIzrBhT7D3Q9c3GFnd0JrPVhn/06U= -github.com/huandu/skiplist v1.2.0 h1:gox56QD77HzSC0w+Ws3MH3iie755GBJU1OER3h5VsYw= -github.com/huandu/skiplist v1.2.0/go.mod h1:7v3iFjLcSAzO4fN5B8dvebvo/qsfumiLiDXMrPiHF9w= +github.com/huandu/skiplist v1.2.1 h1:dTi93MgjwErA/8idWTzIw4Y1kZsMWx35fmI2c8Rij7w= +github.com/huandu/skiplist v1.2.1/go.mod h1:7v3iFjLcSAzO4fN5B8dvebvo/qsfumiLiDXMrPiHF9w= github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI= github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= @@ -402,8 +404,8 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= -github.com/prometheus/client_golang v1.20.3 h1:oPksm4K8B+Vt35tUhw6GbSNSgVlVSBH0qELP/7u83l4= -github.com/prometheus/client_golang v1.20.3/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_golang v1.20.4 h1:Tgh3Yr67PaOv/uTqloMsCEdeuFTatm5zIq5+qNN23vI= +github.com/prometheus/client_golang v1.20.4/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -412,8 +414,8 @@ github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= -github.com/prometheus/common v0.59.1 h1:LXb1quJHWm1P6wq/U824uxYi4Sg0oGvNeUm1z5dJoX0= -github.com/prometheus/common v0.59.1/go.mod h1:GpWM7dewqmVYcd7SmRaiWVe9SSqjf0UrwnYnpEZNuT0= +github.com/prometheus/common v0.60.0 h1:+V9PAREWNvJMAuJ1x1BaWl9dewMW4YrHZQbx0sJNllA= +github.com/prometheus/common v0.60.0/go.mod h1:h0LYf1R1deLSKtD4Vdg8gy4RuOvENW2J/h19V5NADQw= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/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= @@ -632,10 +634,10 @@ google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEY google.golang.org/genproto v0.0.0-20220314164441-57ef72a4c106/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E= google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de h1:F6qOa9AZTYJXOUEr4jDysRDLrm4PHePlge4v4TGAlxY= google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:VUhTRKeHn9wwcdrk73nvdC9gF178Tzhmt/qyaFcPLSo= -google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 h1:+rdxYoE3E5htTEWIe15GlN6IfvbURM//Jt0mmkmm6ZU= -google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117/go.mod h1:OimBR/bc1wPO9iV4NC2bpyjy3VnAwZh5EBPQdtaE5oo= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:pPJltXNxVzT4pK9yD8vR9X75DaWYYmLGMsEvBfFQZzQ= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= +google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 h1:wKguEg1hsxI2/L3hUYrpo1RVi48K+uTyzKqprwLXsb8= +google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142/go.mod h1:d6be+8HhtEtucleCbxpPW9PA9XwISACu8nvpPqF0BVo= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f h1:cUMEy+8oS78BWIH9OWazBkzbr090Od9tWBNtZHkOhf0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= @@ -646,8 +648,8 @@ google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= -google.golang.org/grpc v1.66.2 h1:3QdXkuq3Bkh7w+ywLdLvM56cmGvQHUMZpiCzt6Rqaoo= -google.golang.org/grpc v1.66.2/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y= +google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E= +google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= 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= diff --git a/x/distribution/client/common/common_test.go b/x/distribution/client/common/common_test.go index 2020e3b8f109..020047024ead 100644 --- a/x/distribution/client/common/common_test.go +++ b/x/distribution/client/common/common_test.go @@ -35,7 +35,6 @@ func TestQueryDelegationRewardsAddrValidation(t *testing.T) { } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { _, _, err := QueryDelegationRewards(clientCtx, tt.args.delAddr, tt.args.valAddr) require.True(t, err != nil, tt.wantErr) diff --git a/x/distribution/depinject.go b/x/distribution/depinject.go index 1701e88b8bf2..4803b4d34c60 100644 --- a/x/distribution/depinject.go +++ b/x/distribution/depinject.go @@ -74,7 +74,7 @@ func ProvideModule(in ModuleInputs) ModuleOutputs { authorityAddr, ) - m := NewAppModule(in.Cdc, k, in.AccountKeeper, in.BankKeeper, in.StakingKeeper) + m := NewAppModule(in.Cdc, k, in.StakingKeeper) return ModuleOutputs{ DistrKeeper: k, diff --git a/x/distribution/go.mod b/x/distribution/go.mod index 1d0ab2329dc9..dac4ae3041e6 100644 --- a/x/distribution/go.mod +++ b/x/distribution/go.mod @@ -3,10 +3,10 @@ module cosmossdk.io/x/distribution go 1.23.1 require ( - cosmossdk.io/api v0.7.5 + cosmossdk.io/api v0.7.6 cosmossdk.io/collections v0.4.0 - cosmossdk.io/core v1.0.0-alpha.2 - cosmossdk.io/core/testing v0.0.0-00010101000000-000000000000 + cosmossdk.io/core v1.0.0-alpha.4 + cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29 cosmossdk.io/depinject v1.0.0 cosmossdk.io/errors v1.0.1 cosmossdk.io/math v1.3.0 @@ -18,20 +18,18 @@ require ( github.com/golang/mock v1.6.0 github.com/golang/protobuf v1.5.4 github.com/grpc-ecosystem/grpc-gateway v1.16.0 - github.com/hashicorp/go-metrics v0.5.3 github.com/pkg/errors v0.9.1 github.com/spf13/cobra v1.8.1 github.com/stretchr/testify v1.9.0 - google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 - google.golang.org/grpc v1.66.2 - gotest.tools/v3 v3.5.1 + google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 + google.golang.org/grpc v1.67.1 ) require ( buf.build/gen/go/cometbft/cometbft/protocolbuffers/go v1.34.2-20240701160653-fedbb9acfd2f.2 // indirect buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.34.2-20240130113600-88ef6483f90f.2 // indirect cosmossdk.io/log v1.4.1 // indirect - cosmossdk.io/schema v0.2.0 // indirect + cosmossdk.io/schema v0.3.1-0.20240930054013-7c6e0388a3f9 // indirect cosmossdk.io/x/bank v0.0.0-20240226161501-23359a0b6d91 // indirect cosmossdk.io/x/tx v0.13.3 // indirect filippo.io/edwards25519 v1.1.0 // indirect @@ -93,13 +91,14 @@ require ( github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c // indirect github.com/hashicorp/go-hclog v1.6.3 // indirect github.com/hashicorp/go-immutable-radix v1.3.1 // indirect + github.com/hashicorp/go-metrics v0.5.3 // indirect github.com/hashicorp/go-plugin v1.6.1 // indirect github.com/hashicorp/golang-lru v1.0.2 // indirect github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/hashicorp/yamux v0.1.1 // indirect github.com/hdevalence/ed25519consensus v0.2.0 // indirect - github.com/huandu/skiplist v1.2.0 // indirect + github.com/huandu/skiplist v1.2.1 // indirect github.com/iancoleman/strcase v0.3.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jmhodges/levigo v1.0.0 // indirect @@ -121,9 +120,9 @@ require ( github.com/pelletier/go-toml/v2 v2.2.3 // indirect github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/client_golang v1.20.3 // indirect + github.com/prometheus/client_golang v1.20.4 // indirect github.com/prometheus/client_model v0.6.1 // indirect - github.com/prometheus/common v0.59.1 // indirect + github.com/prometheus/common v0.60.0 // indirect github.com/prometheus/procfs v0.15.1 // indirect github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect github.com/rogpeppe/go-internal v1.12.0 // indirect @@ -159,10 +158,11 @@ require ( golang.org/x/text v0.18.0 // indirect golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f // indirect google.golang.org/protobuf v1.34.2 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect + gotest.tools/v3 v3.5.1 // indirect pgregory.net/rapid v1.1.0 // indirect sigs.k8s.io/yaml v1.4.0 // indirect ) @@ -173,7 +173,6 @@ replace github.com/cosmos/cosmos-sdk => ../../. replace ( cosmossdk.io/api => ../../api cosmossdk.io/collections => ../../collections - cosmossdk.io/core/testing => ../../core/testing cosmossdk.io/store => ../../store cosmossdk.io/x/bank => ../bank cosmossdk.io/x/protocolpool => ../protocolpool diff --git a/x/distribution/go.sum b/x/distribution/go.sum index cd6b45de5cf6..7588b565a0d7 100644 --- a/x/distribution/go.sum +++ b/x/distribution/go.sum @@ -4,8 +4,10 @@ buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.34.2-20240130113600-88e buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.34.2-20240130113600-88ef6483f90f.2/go.mod h1:HqcXMSa5qnNuakaMUo+hWhF51mKbcrZxGl9Vp5EeJXc= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cosmossdk.io/core v1.0.0-alpha.2 h1:epU0Xwces4Rgl5bMhHHkXGaGDcyucNGlC/JDH+Suckg= -cosmossdk.io/core v1.0.0-alpha.2/go.mod h1:abgLjeFLhtuKIYZWSPlVUgQBrKObO7ULV35KYfexE90= +cosmossdk.io/core v1.0.0-alpha.4 h1:9iuroT9ejDYETCsGkzkvs/wAY/5UFl7nCIINFRxyMJY= +cosmossdk.io/core v1.0.0-alpha.4/go.mod h1:3u9cWq1FAVtiiCrDPpo4LhR+9V6k/ycSG4/Y/tREWCY= +cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29 h1:NxxUo0GMJUbIuVg0R70e3cbn9eFTEuMr7ev1AFvypdY= +cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29/go.mod h1:8s2tPeJtSiQuoyPmr2Ag7meikonISO4Fv4MoO8+ORrs= cosmossdk.io/depinject v1.0.0 h1:dQaTu6+O6askNXO06+jyeUAnF2/ssKwrrszP9t5q050= cosmossdk.io/depinject v1.0.0/go.mod h1:zxK/h3HgHoA/eJVtiSsoaRaRA2D5U4cJ5thIG4ssbB8= cosmossdk.io/errors v1.0.1 h1:bzu+Kcr0kS/1DuPBtUFdWjzLqyUuCiyHjyJB6srBV/0= @@ -14,8 +16,8 @@ cosmossdk.io/log v1.4.1 h1:wKdjfDRbDyZRuWa8M+9nuvpVYxrEOwbD/CA8hvhU8QM= cosmossdk.io/log v1.4.1/go.mod h1:k08v0Pyq+gCP6phvdI6RCGhLf/r425UT6Rk/m+o74rU= cosmossdk.io/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE= cosmossdk.io/math v1.3.0/go.mod h1:vnRTxewy+M7BtXBNFybkuhSH4WfedVAAnERHgVFhp3k= -cosmossdk.io/schema v0.2.0 h1:UH5CR1DqUq8yP+5Np8PbvG4YX0zAUsTN2Qk6yThmfMk= -cosmossdk.io/schema v0.2.0/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= +cosmossdk.io/schema v0.3.1-0.20240930054013-7c6e0388a3f9 h1:DmOoS/1PeY6Ih0hAVlJ69kLMUrLV+TCbfICrZtB1vdU= +cosmossdk.io/schema v0.3.1-0.20240930054013-7c6e0388a3f9/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMbk2FiG/kXiLl8BRyzTWDw7gX/Hz7Dd5eDMs= @@ -290,8 +292,8 @@ github.com/hdevalence/ed25519consensus v0.2.0/go.mod h1:w3BHWjwJbFU29IRHL1Iqkw3s github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/huandu/go-assert v1.1.5 h1:fjemmA7sSfYHJD7CUqs9qTwwfdNAx7/j2/ZlHXzNB3c= github.com/huandu/go-assert v1.1.5/go.mod h1:yOLvuqZwmcHIC5rIzrBhT7D3Q9c3GFnd0JrPVhn/06U= -github.com/huandu/skiplist v1.2.0 h1:gox56QD77HzSC0w+Ws3MH3iie755GBJU1OER3h5VsYw= -github.com/huandu/skiplist v1.2.0/go.mod h1:7v3iFjLcSAzO4fN5B8dvebvo/qsfumiLiDXMrPiHF9w= +github.com/huandu/skiplist v1.2.1 h1:dTi93MgjwErA/8idWTzIw4Y1kZsMWx35fmI2c8Rij7w= +github.com/huandu/skiplist v1.2.1/go.mod h1:7v3iFjLcSAzO4fN5B8dvebvo/qsfumiLiDXMrPiHF9w= github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI= github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= @@ -400,8 +402,8 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= -github.com/prometheus/client_golang v1.20.3 h1:oPksm4K8B+Vt35tUhw6GbSNSgVlVSBH0qELP/7u83l4= -github.com/prometheus/client_golang v1.20.3/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_golang v1.20.4 h1:Tgh3Yr67PaOv/uTqloMsCEdeuFTatm5zIq5+qNN23vI= +github.com/prometheus/client_golang v1.20.4/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -410,8 +412,8 @@ github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= -github.com/prometheus/common v0.59.1 h1:LXb1quJHWm1P6wq/U824uxYi4Sg0oGvNeUm1z5dJoX0= -github.com/prometheus/common v0.59.1/go.mod h1:GpWM7dewqmVYcd7SmRaiWVe9SSqjf0UrwnYnpEZNuT0= +github.com/prometheus/common v0.60.0 h1:+V9PAREWNvJMAuJ1x1BaWl9dewMW4YrHZQbx0sJNllA= +github.com/prometheus/common v0.60.0/go.mod h1:h0LYf1R1deLSKtD4Vdg8gy4RuOvENW2J/h19V5NADQw= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/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= @@ -634,10 +636,10 @@ google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEY google.golang.org/genproto v0.0.0-20220314164441-57ef72a4c106/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E= google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de h1:F6qOa9AZTYJXOUEr4jDysRDLrm4PHePlge4v4TGAlxY= google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:VUhTRKeHn9wwcdrk73nvdC9gF178Tzhmt/qyaFcPLSo= -google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 h1:+rdxYoE3E5htTEWIe15GlN6IfvbURM//Jt0mmkmm6ZU= -google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117/go.mod h1:OimBR/bc1wPO9iV4NC2bpyjy3VnAwZh5EBPQdtaE5oo= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:pPJltXNxVzT4pK9yD8vR9X75DaWYYmLGMsEvBfFQZzQ= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= +google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 h1:wKguEg1hsxI2/L3hUYrpo1RVi48K+uTyzKqprwLXsb8= +google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142/go.mod h1:d6be+8HhtEtucleCbxpPW9PA9XwISACu8nvpPqF0BVo= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f h1:cUMEy+8oS78BWIH9OWazBkzbr090Od9tWBNtZHkOhf0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= @@ -648,8 +650,8 @@ google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= -google.golang.org/grpc v1.66.2 h1:3QdXkuq3Bkh7w+ywLdLvM56cmGvQHUMZpiCzt6Rqaoo= -google.golang.org/grpc v1.66.2/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y= +google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E= +google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= 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= diff --git a/x/distribution/keeper/abci.go b/x/distribution/keeper/abci.go index 5831ee9e1b9d..361a329a6108 100644 --- a/x/distribution/keeper/abci.go +++ b/x/distribution/keeper/abci.go @@ -11,7 +11,8 @@ import ( // BeginBlocker sets the proposer for determining distribution during endblock // and distribute rewards for the previous block. func (k Keeper) BeginBlocker(ctx context.Context) error { - defer telemetry.ModuleMeasureSince(types.ModuleName, telemetry.Now(), telemetry.MetricKeyBeginBlocker) + start := telemetry.Now() + defer telemetry.ModuleMeasureSince(types.ModuleName, start, telemetry.MetricKeyBeginBlocker) // determine the total power signing the block var previousTotalPower int64 diff --git a/x/distribution/keeper/grpc_query_test.go b/x/distribution/keeper/grpc_query_test.go index 84fa95def6cc..24271354930f 100644 --- a/x/distribution/keeper/grpc_query_test.go +++ b/x/distribution/keeper/grpc_query_test.go @@ -38,7 +38,6 @@ func TestQueryParams(t *testing.T) { } for _, tc := range cases { - tc := tc t.Run(tc.name, func(t *testing.T) { out, err := queryServer.Params(ctx, tc.req) if tc.errMsg == "" { @@ -94,7 +93,6 @@ func TestQueryValidatorDistributionInfo(t *testing.T) { } for _, tc := range cases { - tc := tc t.Run(tc.name, func(t *testing.T) { out, err := queryServer.ValidatorDistributionInfo(ctx, tc.req) if tc.errMsg == "" { @@ -173,7 +171,6 @@ func TestQueryCommunityPool(t *testing.T) { } for _, tc := range cases { - tc := tc t.Run(tc.name, func(t *testing.T) { out, err := queryServer.CommunityPool(ctx, tc.req) if tc.errMsg == "" { diff --git a/x/distribution/keeper/msg_server.go b/x/distribution/keeper/msg_server.go index 0a4b9f32ca49..5d1fbdcba553 100644 --- a/x/distribution/keeper/msg_server.go +++ b/x/distribution/keeper/msg_server.go @@ -4,12 +4,9 @@ import ( "context" "fmt" - "github.com/hashicorp/go-metrics" - "cosmossdk.io/errors" "cosmossdk.io/x/distribution/types" - "github.com/cosmos/cosmos-sdk/telemetry" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" ) @@ -61,18 +58,6 @@ func (k msgServer) WithdrawDelegatorReward(ctx context.Context, msg *types.MsgWi return nil, err } - defer func() { - for _, a := range amount { - if a.Amount.IsInt64() { - telemetry.SetGaugeWithLabels( - []string{"tx", "msg", "withdraw_reward"}, - float32(a.Amount.Int64()), - []metrics.Label{telemetry.NewLabel("denom", a.Denom)}, - ) - } - } - }() - return &types.MsgWithdrawDelegatorRewardResponse{Amount: amount}, nil } @@ -87,18 +72,6 @@ func (k msgServer) WithdrawValidatorCommission(ctx context.Context, msg *types.M return nil, err } - defer func() { - for _, a := range amount { - if a.Amount.IsInt64() { - telemetry.SetGaugeWithLabels( - []string{"tx", "msg", "withdraw_commission"}, - float32(a.Amount.Int64()), - []metrics.Label{telemetry.NewLabel("denom", a.Denom)}, - ) - } - } - }() - return &types.MsgWithdrawValidatorCommissionResponse{Amount: amount}, nil } diff --git a/x/distribution/keeper/msg_server_test.go b/x/distribution/keeper/msg_server_test.go index 03f4e8c88565..a7acde70e34b 100644 --- a/x/distribution/keeper/msg_server_test.go +++ b/x/distribution/keeper/msg_server_test.go @@ -56,7 +56,6 @@ func TestMsgSetWithdrawAddress(t *testing.T) { } for _, tc := range cases { - tc := tc t.Run(tc.name, func(t *testing.T) { _, err := msgServer.SetWithdrawAddress(ctx, tc.msg) if tc.errMsg == "" { @@ -112,7 +111,6 @@ func TestMsgWithdrawDelegatorReward(t *testing.T) { } for _, tc := range cases { - tc := tc t.Run(tc.name, func(t *testing.T) { if tc.preRun != nil { tc.preRun() @@ -158,7 +156,6 @@ func TestMsgWithdrawValidatorCommission(t *testing.T) { } for _, tc := range cases { - tc := tc t.Run(tc.name, func(t *testing.T) { if tc.preRun != nil { tc.preRun() @@ -206,7 +203,6 @@ func TestMsgFundCommunityPool(t *testing.T) { } for _, tc := range cases { - tc := tc t.Run(tc.name, func(t *testing.T) { _, err := msgServer.FundCommunityPool(ctx, tc.msg) //nolint:staticcheck // Testing deprecated method if tc.errMsg == "" { @@ -267,7 +263,6 @@ func TestMsgUpdateParams(t *testing.T) { } for _, tc := range cases { - tc := tc t.Run(tc.name, func(t *testing.T) { _, err := msgServer.UpdateParams(ctx, tc.msg) if tc.errMsg == "" { @@ -340,7 +335,6 @@ func TestMsgCommunityPoolSpend(t *testing.T) { } for _, tc := range cases { - tc := tc t.Run(tc.name, func(t *testing.T) { _, err := msgServer.CommunityPoolSpend(ctx, tc.msg) //nolint:staticcheck // Testing deprecated method if tc.errMsg == "" { @@ -373,7 +367,6 @@ func TestMsgDepositValidatorRewardsPool(t *testing.T) { } for _, tc := range cases { - tc := tc t.Run(tc.name, func(t *testing.T) { _, err := msgServer.DepositValidatorRewardsPool(ctx, tc.msg) if tc.errMsg == "" { diff --git a/x/distribution/module.go b/x/distribution/module.go index db043b3bdabe..eb7de978c6d1 100644 --- a/x/distribution/module.go +++ b/x/distribution/module.go @@ -18,6 +18,7 @@ import ( sdkclient "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/simsx" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/module" simtypes "github.com/cosmos/cosmos-sdk/types/simulation" @@ -43,21 +44,14 @@ var ( type AppModule struct { cdc codec.Codec keeper keeper.Keeper - accountKeeper types.AccountKeeper - bankKeeper types.BankKeeper stakingKeeper types.StakingKeeper } // NewAppModule creates a new AppModule object -func NewAppModule( - cdc codec.Codec, keeper keeper.Keeper, accountKeeper types.AccountKeeper, - bankKeeper types.BankKeeper, stakingKeeper types.StakingKeeper, -) AppModule { +func NewAppModule(cdc codec.Codec, keeper keeper.Keeper, stakingKeeper types.StakingKeeper) AppModule { return AppModule{ cdc: cdc, keeper: keeper, - accountKeeper: accountKeeper, - bankKeeper: bankKeeper, stakingKeeper: stakingKeeper, } } @@ -173,20 +167,18 @@ func (AppModule) GenerateGenesisState(simState *module.SimulationState) { simulation.RandomizedGenState(simState) } -// ProposalMsgs returns msgs used for governance proposals for simulations. -func (AppModule) ProposalMsgs(_ module.SimulationState) []simtypes.WeightedProposalMsg { - return simulation.ProposalMsgs() -} - // RegisterStoreDecoder registers a decoder for distribution module's types func (am AppModule) RegisterStoreDecoder(sdr simtypes.StoreDecoderRegistry) { sdr[types.StoreKey] = simulation.NewDecodeStore(am.cdc) } -// WeightedOperations returns the all the gov module operations with their respective weights. -func (am AppModule) WeightedOperations(simState module.SimulationState) []simtypes.WeightedOperation { - return simulation.WeightedOperations( - simState.AppParams, simState.Cdc, simState.TxConfig, - am.accountKeeper, am.bankKeeper, am.keeper, am.stakingKeeper, - ) +// ProposalMsgsX returns msgs used for governance proposals for simulations. +func (AppModule) ProposalMsgsX(weights simsx.WeightSource, reg simsx.Registry) { + reg.Add(weights.Get("msg_update_params", 100), simulation.MsgUpdateParamsFactory()) +} + +func (am AppModule) WeightedOperationsX(weights simsx.WeightSource, reg simsx.Registry) { + reg.Add(weights.Get("msg_set_withdraw_address", 50), simulation.MsgSetWithdrawAddressFactory(am.keeper)) + reg.Add(weights.Get("msg_withdraw_delegation_reward", 50), simulation.MsgWithdrawDelegatorRewardFactory(am.keeper, am.stakingKeeper)) + reg.Add(weights.Get("msg_withdraw_validator_commission", 50), simulation.MsgWithdrawValidatorCommissionFactory(am.keeper, am.stakingKeeper)) } diff --git a/x/distribution/simulation/decoder_test.go b/x/distribution/simulation/decoder_test.go index c96f8444840f..52b4d1b4886f 100644 --- a/x/distribution/simulation/decoder_test.go +++ b/x/distribution/simulation/decoder_test.go @@ -51,7 +51,6 @@ func TestDecodeDistributionStore(t *testing.T) { {"other", ""}, } for i, tt := range tests { - i, tt := i, tt t.Run(tt.name, func(t *testing.T) { switch i { case len(tests) - 1: diff --git a/x/distribution/simulation/genesis.go b/x/distribution/simulation/genesis.go index bccf952ad99d..4b0c42c9b467 100644 --- a/x/distribution/simulation/genesis.go +++ b/x/distribution/simulation/genesis.go @@ -1,8 +1,6 @@ package simulation import ( - "encoding/json" - "fmt" "math/rand" "cosmossdk.io/math" @@ -43,10 +41,5 @@ func RandomizedGenState(simState *module.SimulationState) { }, } - bz, err := json.MarshalIndent(&distrGenesis, "", " ") - if err != nil { - panic(err) - } - fmt.Printf("Selected randomly generated distribution parameters:\n%s\n", bz) simState.GenState[types.ModuleName] = simState.Cdc.MustMarshalJSON(&distrGenesis) } diff --git a/x/distribution/simulation/genesis_test.go b/x/distribution/simulation/genesis_test.go index 6c74a5e2bffc..46ff6aedb755 100644 --- a/x/distribution/simulation/genesis_test.go +++ b/x/distribution/simulation/genesis_test.go @@ -77,8 +77,6 @@ func TestRandomizedGenState1(t *testing.T) { } for _, tt := range tests { - tt := tt - require.Panicsf(t, func() { simulation.RandomizedGenState(&tt.simState) }, tt.panicMsg) } } diff --git a/x/distribution/simulation/msg_factory.go b/x/distribution/simulation/msg_factory.go new file mode 100644 index 000000000000..2a494dd90c31 --- /dev/null +++ b/x/distribution/simulation/msg_factory.go @@ -0,0 +1,125 @@ +package simulation + +import ( + "context" + "errors" + + "cosmossdk.io/collections" + sdkmath "cosmossdk.io/math" + "cosmossdk.io/x/distribution/keeper" + "cosmossdk.io/x/distribution/types" + + "github.com/cosmos/cosmos-sdk/simsx" +) + +func MsgSetWithdrawAddressFactory(k keeper.Keeper) simsx.SimMsgFactoryFn[*types.MsgSetWithdrawAddress] { + return func(ctx context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter) ([]simsx.SimAccount, *types.MsgSetWithdrawAddress) { + switch enabled, err := k.GetWithdrawAddrEnabled(ctx); { + case err != nil: + reporter.Skip("error getting params") + return nil, nil + case !enabled: + reporter.Skip("withdrawal is not enabled") + return nil, nil + } + delegator := testData.AnyAccount(reporter) + withdrawer := testData.AnyAccount(reporter, simsx.ExcludeAccounts(delegator)) + msg := types.NewMsgSetWithdrawAddress(delegator.AddressBech32, withdrawer.AddressBech32) + return []simsx.SimAccount{delegator}, msg + } +} + +func MsgWithdrawDelegatorRewardFactory(k keeper.Keeper, sk types.StakingKeeper) simsx.SimMsgFactoryFn[*types.MsgWithdrawDelegatorReward] { + return func(ctx context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter) ([]simsx.SimAccount, *types.MsgWithdrawDelegatorReward) { + delegator := testData.AnyAccount(reporter) + + delegations, err := sk.GetAllDelegatorDelegations(ctx, delegator.Address) + switch { + case err != nil: + reporter.Skipf("error getting delegations: %v", err) + return nil, nil + case len(delegations) == 0: + reporter.Skip("no delegations found") + return nil, nil + } + delegation := delegations[testData.Rand().Intn(len(delegations))] + + valAddr, err := sk.ValidatorAddressCodec().StringToBytes(delegation.GetValidatorAddr()) + if err != nil { + reporter.Skip(err.Error()) + return nil, nil + } + + var valOper string + switch validator, err := sk.Validator(ctx, valAddr); { + case err != nil: + reporter.Skip(err.Error()) + return nil, nil + case validator == nil: + reporter.Skipf("validator %s not found", delegation.GetValidatorAddr()) + return nil, nil + default: + valOper = validator.GetOperator() + } + // get outstanding rewards so we can first check if the withdrawable coins are sendable + outstanding, err := k.GetValidatorOutstandingRewardsCoins(ctx, valAddr) + if err != nil { + reporter.Skipf("get outstanding rewards: %v", err) + return nil, nil + } + + for _, v := range outstanding { + if !testData.IsSendEnabledDenom(v.Denom) { + reporter.Skipf("denom send not enabled: " + v.Denom) + return nil, nil + } + } + + msg := types.NewMsgWithdrawDelegatorReward(delegator.AddressBech32, valOper) + return []simsx.SimAccount{delegator}, msg + } +} + +func MsgWithdrawValidatorCommissionFactory(k keeper.Keeper, sk types.StakingKeeper) simsx.SimMsgFactoryFn[*types.MsgWithdrawValidatorCommission] { + return func(ctx context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter) ([]simsx.SimAccount, *types.MsgWithdrawValidatorCommission) { + allVals, err := sk.GetAllValidators(ctx) + if err != nil { + reporter.Skip(err.Error()) + return nil, nil + } + val := simsx.OneOf(testData.Rand(), allVals) + valAddrBz, err := sk.ValidatorAddressCodec().StringToBytes(val.GetOperator()) + if err != nil { + reporter.Skip(err.Error()) + return nil, nil + } + + commission, err := k.ValidatorsAccumulatedCommission.Get(ctx, valAddrBz) + if err != nil && !errors.Is(err, collections.ErrNotFound) { + reporter.Skip(err.Error()) + return nil, nil + } + + if commission.Commission.IsZero() { + reporter.Skip("validator commission is zero") + return nil, nil + } + msg := types.NewMsgWithdrawValidatorCommission(val.GetOperator()) + valAccount := testData.GetAccountbyAccAddr(reporter, valAddrBz) + return []simsx.SimAccount{valAccount}, msg + } +} + +func MsgUpdateParamsFactory() simsx.SimMsgFactoryFn[*types.MsgUpdateParams] { + return func(_ context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter) ([]simsx.SimAccount, *types.MsgUpdateParams) { + r := testData.Rand() + params := types.DefaultParams() + params.CommunityTax = r.DecN(sdkmath.LegacyNewDec(1)) + params.WithdrawAddrEnabled = r.Intn(2) == 0 + + return nil, &types.MsgUpdateParams{ + Authority: testData.ModuleAccountAddress(reporter, "gov"), + Params: params, + } + } +} diff --git a/x/distribution/simulation/operations.go b/x/distribution/simulation/operations.go deleted file mode 100644 index 4b067cbe7174..000000000000 --- a/x/distribution/simulation/operations.go +++ /dev/null @@ -1,247 +0,0 @@ -package simulation - -import ( - "fmt" - "math/rand" - - "github.com/pkg/errors" - - "cosmossdk.io/collections" - "cosmossdk.io/x/distribution/keeper" - "cosmossdk.io/x/distribution/types" - - "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/codec" - "github.com/cosmos/cosmos-sdk/testutil" - sdk "github.com/cosmos/cosmos-sdk/types" - simtypes "github.com/cosmos/cosmos-sdk/types/simulation" - "github.com/cosmos/cosmos-sdk/x/simulation" -) - -// Simulation operation weights constants -const ( - OpWeightMsgSetWithdrawAddress = "op_weight_msg_set_withdraw_address" - OpWeightMsgWithdrawDelegationReward = "op_weight_msg_withdraw_delegation_reward" - OpWeightMsgWithdrawValidatorCommission = "op_weight_msg_withdraw_validator_commission" - - DefaultWeightMsgSetWithdrawAddress int = 50 - DefaultWeightMsgWithdrawDelegationReward int = 50 - DefaultWeightMsgWithdrawValidatorCommission int = 50 -) - -// WeightedOperations returns all the operations from the module with their respective weights -func WeightedOperations( - appParams simtypes.AppParams, - cdc codec.JSONCodec, - txConfig client.TxConfig, - ak types.AccountKeeper, - bk types.BankKeeper, - k keeper.Keeper, - sk types.StakingKeeper, -) simulation.WeightedOperations { - var weightMsgSetWithdrawAddress int - appParams.GetOrGenerate(OpWeightMsgSetWithdrawAddress, &weightMsgSetWithdrawAddress, nil, func(_ *rand.Rand) { - weightMsgSetWithdrawAddress = DefaultWeightMsgSetWithdrawAddress - }) - - var weightMsgWithdrawDelegationReward int - appParams.GetOrGenerate(OpWeightMsgWithdrawDelegationReward, &weightMsgWithdrawDelegationReward, nil, func(_ *rand.Rand) { - weightMsgWithdrawDelegationReward = DefaultWeightMsgWithdrawDelegationReward - }) - - var weightMsgWithdrawValidatorCommission int - appParams.GetOrGenerate(OpWeightMsgWithdrawValidatorCommission, &weightMsgWithdrawValidatorCommission, nil, func(_ *rand.Rand) { - weightMsgWithdrawValidatorCommission = DefaultWeightMsgWithdrawValidatorCommission - }) - - return simulation.WeightedOperations{ - simulation.NewWeightedOperation( - weightMsgSetWithdrawAddress, - SimulateMsgSetWithdrawAddress(txConfig, ak, bk, k), - ), - simulation.NewWeightedOperation( - weightMsgWithdrawDelegationReward, - SimulateMsgWithdrawDelegatorReward(txConfig, ak, bk, k, sk), - ), - simulation.NewWeightedOperation( - weightMsgWithdrawValidatorCommission, - SimulateMsgWithdrawValidatorCommission(txConfig, ak, bk, k, sk), - ), - } -} - -// SimulateMsgSetWithdrawAddress generates a MsgSetWithdrawAddress with random values. -func SimulateMsgSetWithdrawAddress(txConfig client.TxConfig, ak types.AccountKeeper, bk types.BankKeeper, k keeper.Keeper) simtypes.Operation { - return func( - r *rand.Rand, app simtypes.AppEntrypoint, ctx sdk.Context, accs []simtypes.Account, chainID string, - ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { - isWithdrawAddrEnabled, err := k.GetWithdrawAddrEnabled(ctx) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(&types.MsgSetWithdrawAddress{}), "error getting params"), nil, err - } - - if !isWithdrawAddrEnabled { - return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(&types.MsgSetWithdrawAddress{}), "withdrawal is not enabled"), nil, nil - } - - simAccount, _ := simtypes.RandomAcc(r, accs) - simToAccount, _ := simtypes.RandomAcc(r, accs) - - account := ak.GetAccount(ctx, simAccount.Address) - spendable := bk.SpendableCoins(ctx, account.GetAddress()) - - addr, err := ak.AddressCodec().BytesToString(simAccount.Address) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(&types.MsgSetWithdrawAddress{}), "error converting delegator address"), nil, err - } - toAddr, err := ak.AddressCodec().BytesToString(simToAccount.Address) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(&types.MsgSetWithdrawAddress{}), "error converting withdraw address"), nil, err - } - - msg := types.NewMsgSetWithdrawAddress(addr, toAddr) - - txCtx := simulation.OperationInput{ - R: r, - App: app, - TxGen: txConfig, - Cdc: nil, - Msg: msg, - Context: ctx, - SimAccount: simAccount, - AccountKeeper: ak, - Bankkeeper: bk, - ModuleName: types.ModuleName, - CoinsSpentInMsg: spendable, - } - - return simulation.GenAndDeliverTxWithRandFees(txCtx) - } -} - -// SimulateMsgWithdrawDelegatorReward generates a MsgWithdrawDelegatorReward with random values. -func SimulateMsgWithdrawDelegatorReward(txConfig client.TxConfig, ak types.AccountKeeper, bk types.BankKeeper, k keeper.Keeper, sk types.StakingKeeper) simtypes.Operation { - return func( - r *rand.Rand, app simtypes.AppEntrypoint, ctx sdk.Context, accs []simtypes.Account, chainID string, - ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { - simAccount, _ := simtypes.RandomAcc(r, accs) - delegations, err := sk.GetAllDelegatorDelegations(ctx, simAccount.Address) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(&types.MsgWithdrawDelegatorReward{}), "error getting delegations"), nil, err - } - if len(delegations) == 0 { - return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(&types.MsgWithdrawDelegatorReward{}), "number of delegators equal 0"), nil, nil - } - - delegation := delegations[r.Intn(len(delegations))] - - delAddr, err := sk.ValidatorAddressCodec().StringToBytes(delegation.GetValidatorAddr()) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(&types.MsgWithdrawDelegatorReward{}), "error converting validator address"), nil, err - } - validator, err := sk.Validator(ctx, delAddr) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(&types.MsgWithdrawDelegatorReward{}), "error getting validator"), nil, err - } - if validator == nil { - return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(&types.MsgWithdrawDelegatorReward{}), "validator is nil"), nil, fmt.Errorf("validator %s not found", delegation.GetValidatorAddr()) - } - - account := ak.GetAccount(ctx, simAccount.Address) - spendable := bk.SpendableCoins(ctx, account.GetAddress()) - - addr, err := ak.AddressCodec().BytesToString(simAccount.Address) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(&types.MsgWithdrawDelegatorReward{}), "error converting delegator address"), nil, err - } - - msg := types.NewMsgWithdrawDelegatorReward(addr, validator.GetOperator()) - - // get outstanding rewards so we can first check if the withdrawable coins are sendable - outstanding, err := k.GetValidatorOutstandingRewardsCoins(ctx, sdk.ValAddress(delAddr)) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(&types.MsgWithdrawDelegatorReward{}), "error getting outstanding rewards"), nil, err - } - - for _, v := range outstanding { - if !bk.IsSendEnabledDenom(ctx, v.Denom) { - return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(msg), "denom send not enabled: "+v.Denom), nil, nil - } - } - - txCtx := simulation.OperationInput{ - R: r, - App: app, - TxGen: txConfig, - Cdc: nil, - Msg: msg, - Context: ctx, - SimAccount: simAccount, - AccountKeeper: ak, - Bankkeeper: bk, - ModuleName: types.ModuleName, - CoinsSpentInMsg: spendable, - } - - return simulation.GenAndDeliverTxWithRandFees(txCtx) - } -} - -// SimulateMsgWithdrawValidatorCommission generates a MsgWithdrawValidatorCommission with random values. -func SimulateMsgWithdrawValidatorCommission(txConfig client.TxConfig, ak types.AccountKeeper, bk types.BankKeeper, k keeper.Keeper, sk types.StakingKeeper) simtypes.Operation { - return func( - r *rand.Rand, app simtypes.AppEntrypoint, ctx sdk.Context, accs []simtypes.Account, chainID string, - ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { - msgType := sdk.MsgTypeURL(&types.MsgWithdrawValidatorCommission{}) - - allVals, err := sk.GetAllValidators(ctx) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "error getting all validators"), nil, err - } - - validator, ok := testutil.RandSliceElem(r, allVals) - if !ok { - return simtypes.NoOpMsg(types.ModuleName, msgType, "random validator is not ok"), nil, nil - } - - valBz, err := sk.ValidatorAddressCodec().StringToBytes(validator.GetOperator()) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "error converting validator address"), nil, err - } - - commission, err := k.ValidatorsAccumulatedCommission.Get(ctx, valBz) - if err != nil && !errors.Is(err, collections.ErrNotFound) { - return simtypes.NoOpMsg(types.ModuleName, msgType, "error getting validator commission"), nil, err - } - - if commission.Commission.IsZero() { - return simtypes.NoOpMsg(types.ModuleName, msgType, "validator commission is zero"), nil, nil - } - - simAccount, found := simtypes.FindAccount(accs, sdk.AccAddress(valBz)) - if !found { - return simtypes.NoOpMsg(types.ModuleName, msgType, "could not find account"), nil, fmt.Errorf("validator %s not found", validator.GetOperator()) - } - - account := ak.GetAccount(ctx, simAccount.Address) - spendable := bk.SpendableCoins(ctx, account.GetAddress()) - - msg := types.NewMsgWithdrawValidatorCommission(validator.GetOperator()) - - txCtx := simulation.OperationInput{ - R: r, - App: app, - TxGen: txConfig, - Cdc: nil, - Msg: msg, - Context: ctx, - SimAccount: simAccount, - AccountKeeper: ak, - Bankkeeper: bk, - ModuleName: types.ModuleName, - CoinsSpentInMsg: spendable, - } - - return simulation.GenAndDeliverTxWithRandFees(txCtx) - } -} diff --git a/x/distribution/simulation/proposals.go b/x/distribution/simulation/proposals.go deleted file mode 100644 index 3d9dfe6bd900..000000000000 --- a/x/distribution/simulation/proposals.go +++ /dev/null @@ -1,53 +0,0 @@ -package simulation - -import ( - "context" - "math/rand" - - coreaddress "cosmossdk.io/core/address" - sdkmath "cosmossdk.io/math" - "cosmossdk.io/x/distribution/types" - - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/types/address" - simtypes "github.com/cosmos/cosmos-sdk/types/simulation" - "github.com/cosmos/cosmos-sdk/x/simulation" -) - -// Simulation operation weights constants -const ( - DefaultWeightMsgUpdateParams int = 50 - - OpWeightMsgUpdateParams = "op_weight_msg_update_params" -) - -// ProposalMsgs defines the module weighted proposals' contents -func ProposalMsgs() []simtypes.WeightedProposalMsg { - return []simtypes.WeightedProposalMsg{ - simulation.NewWeightedProposalMsgX( - OpWeightMsgUpdateParams, - DefaultWeightMsgUpdateParams, - SimulateMsgUpdateParams, - ), - } -} - -// SimulateMsgUpdateParams returns a random MsgUpdateParams -func SimulateMsgUpdateParams(_ context.Context, r *rand.Rand, _ []simtypes.Account, cdc coreaddress.Codec) (sdk.Msg, error) { - // use the default gov module account address as authority - var authority sdk.AccAddress = address.Module("gov") - - params := types.DefaultParams() - params.CommunityTax = simtypes.RandomDecAmount(r, sdkmath.LegacyNewDec(1)) - params.WithdrawAddrEnabled = r.Intn(2) == 0 - - authorityAddr, err := cdc.BytesToString(authority) - if err != nil { - return nil, err - } - - return &types.MsgUpdateParams{ - Authority: authorityAddr, - Params: params, - }, nil -} diff --git a/x/distribution/simulation/proposals_test.go b/x/distribution/simulation/proposals_test.go deleted file mode 100644 index ce792ea856e4..000000000000 --- a/x/distribution/simulation/proposals_test.go +++ /dev/null @@ -1,47 +0,0 @@ -package simulation_test - -import ( - "context" - "math/rand" - "testing" - - "gotest.tools/v3/assert" - - sdkmath "cosmossdk.io/math" - "cosmossdk.io/x/distribution/simulation" - "cosmossdk.io/x/distribution/types" - - codectestutil "github.com/cosmos/cosmos-sdk/codec/testutil" - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/types/address" - simtypes "github.com/cosmos/cosmos-sdk/types/simulation" -) - -func TestProposalMsgs(t *testing.T) { - // initialize parameters - s := rand.NewSource(1) - r := rand.New(s) - addressCodec := codectestutil.CodecOptions{}.GetAddressCodec() - accounts := simtypes.RandomAccounts(r, 3) - - // execute ProposalMsgs function - weightedProposalMsgs := simulation.ProposalMsgs() - assert.Assert(t, len(weightedProposalMsgs) == 1) - - w0 := weightedProposalMsgs[0] - - // tests w0 interface: - assert.Equal(t, simulation.OpWeightMsgUpdateParams, w0.AppParamsKey()) - assert.Equal(t, simulation.DefaultWeightMsgUpdateParams, w0.DefaultWeight()) - - msg, err := w0.MsgSimulatorFn()(context.Background(), r, accounts, addressCodec) - assert.NilError(t, err) - msgUpdateParams, ok := msg.(*types.MsgUpdateParams) - assert.Assert(t, ok) - - addr, err := addressCodec.BytesToString(sdk.AccAddress(address.Module("gov"))) - assert.NilError(t, err) - assert.Equal(t, addr, msgUpdateParams.Authority) - assert.DeepEqual(t, sdkmath.LegacyNewDec(0), msgUpdateParams.Params.CommunityTax) - assert.Equal(t, true, msgUpdateParams.Params.WithdrawAddrEnabled) -} diff --git a/x/distribution/types/params_internal_test.go b/x/distribution/types/params_internal_test.go index 92cffd78460b..21bfd0f1bf16 100644 --- a/x/distribution/types/params_internal_test.go +++ b/x/distribution/types/params_internal_test.go @@ -24,7 +24,6 @@ func Test_validateAuxFuncs(t *testing.T) { {"two dec", args{math.LegacyNewDec(2)}, true}, } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { require.Equal(t, tt.wantErr, validateCommunityTax(tt.args.i) != nil) }) diff --git a/x/epochs/README.md b/x/epochs/README.md index dcd7eb7b5176..7b0b0b285767 100644 --- a/x/epochs/README.md +++ b/x/epochs/README.md @@ -68,22 +68,6 @@ The `epochs` module emits the following events: Epochs keeper module provides utility functions to manage epochs. -``` go -// Keeper is the interface for epochs module keeper -type Keeper interface { - // GetEpochInfo returns epoch info by identifier - GetEpochInfo(ctx sdk.Context, identifier string) types.EpochInfo - // SetEpochInfo set epoch info - SetEpochInfo(ctx sdk.Context, epoch types.EpochInfo) - // DeleteEpochInfo delete epoch info - DeleteEpochInfo(ctx sdk.Context, identifier string) - // IterateEpochInfo iterate through epochs - IterateEpochInfo(ctx sdk.Context, fn func(index int64, epochInfo types.EpochInfo) (stop bool)) - // Get all epoch infos - AllEpochInfos(ctx sdk.Context) []types.EpochInfo -} -``` - ## Hooks ```go diff --git a/x/epochs/go.mod b/x/epochs/go.mod index 577509b1f8f0..b8262cba4f35 100644 --- a/x/epochs/go.mod +++ b/x/epochs/go.mod @@ -3,10 +3,10 @@ module cosmossdk.io/x/epochs go 1.23.1 require ( - cosmossdk.io/api v0.7.5 + cosmossdk.io/api v0.7.6 cosmossdk.io/collections v0.4.0 - cosmossdk.io/core v1.0.0-alpha.2 - cosmossdk.io/core/testing v0.0.0-00010101000000-000000000000 + cosmossdk.io/core v1.0.0-alpha.4 + cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29 cosmossdk.io/depinject v1.0.0 cosmossdk.io/errors v1.0.1 cosmossdk.io/store v1.1.1-0.20240418092142-896cdf1971bc @@ -16,11 +16,11 @@ require ( github.com/golang/protobuf v1.5.4 github.com/grpc-ecosystem/grpc-gateway v1.16.0 github.com/stretchr/testify v1.9.0 - google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 - google.golang.org/grpc v1.66.2 + google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 + google.golang.org/grpc v1.67.1 ) -require cosmossdk.io/schema v0.2.0 // indirect +require cosmossdk.io/schema v0.3.1-0.20240930054013-7c6e0388a3f9 // indirect require ( buf.build/gen/go/cometbft/cometbft/protocolbuffers/go v1.34.2-20240701160653-fedbb9acfd2f.2 // indirect @@ -94,7 +94,7 @@ require ( github.com/hashicorp/hcl v1.0.0 // indirect github.com/hashicorp/yamux v0.1.1 // indirect github.com/hdevalence/ed25519consensus v0.2.0 // indirect - github.com/huandu/skiplist v1.2.0 // indirect + github.com/huandu/skiplist v1.2.1 // indirect github.com/iancoleman/strcase v0.3.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jmhodges/levigo v1.0.0 // indirect @@ -117,9 +117,9 @@ require ( github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/client_golang v1.20.3 // indirect + github.com/prometheus/client_golang v1.20.4 // indirect github.com/prometheus/client_model v0.6.1 // indirect - github.com/prometheus/common v0.59.1 // indirect + github.com/prometheus/common v0.60.0 // indirect github.com/prometheus/procfs v0.15.1 // indirect github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect github.com/rogpeppe/go-internal v1.12.0 // indirect @@ -156,7 +156,7 @@ require ( golang.org/x/text v0.18.0 // indirect golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f // indirect google.golang.org/protobuf v1.34.2 gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect @@ -175,7 +175,6 @@ replace github.com/cosmos/cosmos-sdk => ../../. // TODO remove post spinning out all modules replace ( cosmossdk.io/api => ../../api - cosmossdk.io/core/testing => ../../core/testing cosmossdk.io/store => ../../store cosmossdk.io/x/bank => ../bank cosmossdk.io/x/staking => ../staking diff --git a/x/epochs/go.sum b/x/epochs/go.sum index 27af6ac5b1b3..6a6b2df0b205 100644 --- a/x/epochs/go.sum +++ b/x/epochs/go.sum @@ -6,8 +6,10 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cosmossdk.io/collections v0.4.0 h1:PFmwj2W8szgpD5nOd8GWH6AbYNi1f2J6akWXJ7P5t9s= cosmossdk.io/collections v0.4.0/go.mod h1:oa5lUING2dP+gdDquow+QjlF45eL1t4TJDypgGd+tv0= -cosmossdk.io/core v1.0.0-alpha.2 h1:epU0Xwces4Rgl5bMhHHkXGaGDcyucNGlC/JDH+Suckg= -cosmossdk.io/core v1.0.0-alpha.2/go.mod h1:abgLjeFLhtuKIYZWSPlVUgQBrKObO7ULV35KYfexE90= +cosmossdk.io/core v1.0.0-alpha.4 h1:9iuroT9ejDYETCsGkzkvs/wAY/5UFl7nCIINFRxyMJY= +cosmossdk.io/core v1.0.0-alpha.4/go.mod h1:3u9cWq1FAVtiiCrDPpo4LhR+9V6k/ycSG4/Y/tREWCY= +cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29 h1:NxxUo0GMJUbIuVg0R70e3cbn9eFTEuMr7ev1AFvypdY= +cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29/go.mod h1:8s2tPeJtSiQuoyPmr2Ag7meikonISO4Fv4MoO8+ORrs= cosmossdk.io/depinject v1.0.0 h1:dQaTu6+O6askNXO06+jyeUAnF2/ssKwrrszP9t5q050= cosmossdk.io/depinject v1.0.0/go.mod h1:zxK/h3HgHoA/eJVtiSsoaRaRA2D5U4cJ5thIG4ssbB8= cosmossdk.io/errors v1.0.1 h1:bzu+Kcr0kS/1DuPBtUFdWjzLqyUuCiyHjyJB6srBV/0= @@ -16,8 +18,8 @@ cosmossdk.io/log v1.4.1 h1:wKdjfDRbDyZRuWa8M+9nuvpVYxrEOwbD/CA8hvhU8QM= cosmossdk.io/log v1.4.1/go.mod h1:k08v0Pyq+gCP6phvdI6RCGhLf/r425UT6Rk/m+o74rU= cosmossdk.io/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE= cosmossdk.io/math v1.3.0/go.mod h1:vnRTxewy+M7BtXBNFybkuhSH4WfedVAAnERHgVFhp3k= -cosmossdk.io/schema v0.2.0 h1:UH5CR1DqUq8yP+5Np8PbvG4YX0zAUsTN2Qk6yThmfMk= -cosmossdk.io/schema v0.2.0/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= +cosmossdk.io/schema v0.3.1-0.20240930054013-7c6e0388a3f9 h1:DmOoS/1PeY6Ih0hAVlJ69kLMUrLV+TCbfICrZtB1vdU= +cosmossdk.io/schema v0.3.1-0.20240930054013-7c6e0388a3f9/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMbk2FiG/kXiLl8BRyzTWDw7gX/Hz7Dd5eDMs= @@ -292,8 +294,8 @@ github.com/hdevalence/ed25519consensus v0.2.0/go.mod h1:w3BHWjwJbFU29IRHL1Iqkw3s github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/huandu/go-assert v1.1.5 h1:fjemmA7sSfYHJD7CUqs9qTwwfdNAx7/j2/ZlHXzNB3c= github.com/huandu/go-assert v1.1.5/go.mod h1:yOLvuqZwmcHIC5rIzrBhT7D3Q9c3GFnd0JrPVhn/06U= -github.com/huandu/skiplist v1.2.0 h1:gox56QD77HzSC0w+Ws3MH3iie755GBJU1OER3h5VsYw= -github.com/huandu/skiplist v1.2.0/go.mod h1:7v3iFjLcSAzO4fN5B8dvebvo/qsfumiLiDXMrPiHF9w= +github.com/huandu/skiplist v1.2.1 h1:dTi93MgjwErA/8idWTzIw4Y1kZsMWx35fmI2c8Rij7w= +github.com/huandu/skiplist v1.2.1/go.mod h1:7v3iFjLcSAzO4fN5B8dvebvo/qsfumiLiDXMrPiHF9w= github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI= github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= @@ -402,8 +404,8 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= -github.com/prometheus/client_golang v1.20.3 h1:oPksm4K8B+Vt35tUhw6GbSNSgVlVSBH0qELP/7u83l4= -github.com/prometheus/client_golang v1.20.3/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_golang v1.20.4 h1:Tgh3Yr67PaOv/uTqloMsCEdeuFTatm5zIq5+qNN23vI= +github.com/prometheus/client_golang v1.20.4/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -412,8 +414,8 @@ github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= -github.com/prometheus/common v0.59.1 h1:LXb1quJHWm1P6wq/U824uxYi4Sg0oGvNeUm1z5dJoX0= -github.com/prometheus/common v0.59.1/go.mod h1:GpWM7dewqmVYcd7SmRaiWVe9SSqjf0UrwnYnpEZNuT0= +github.com/prometheus/common v0.60.0 h1:+V9PAREWNvJMAuJ1x1BaWl9dewMW4YrHZQbx0sJNllA= +github.com/prometheus/common v0.60.0/go.mod h1:h0LYf1R1deLSKtD4Vdg8gy4RuOvENW2J/h19V5NADQw= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/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= @@ -632,10 +634,10 @@ google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEY google.golang.org/genproto v0.0.0-20220314164441-57ef72a4c106/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E= google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de h1:F6qOa9AZTYJXOUEr4jDysRDLrm4PHePlge4v4TGAlxY= google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:VUhTRKeHn9wwcdrk73nvdC9gF178Tzhmt/qyaFcPLSo= -google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 h1:+rdxYoE3E5htTEWIe15GlN6IfvbURM//Jt0mmkmm6ZU= -google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117/go.mod h1:OimBR/bc1wPO9iV4NC2bpyjy3VnAwZh5EBPQdtaE5oo= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:pPJltXNxVzT4pK9yD8vR9X75DaWYYmLGMsEvBfFQZzQ= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= +google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 h1:wKguEg1hsxI2/L3hUYrpo1RVi48K+uTyzKqprwLXsb8= +google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142/go.mod h1:d6be+8HhtEtucleCbxpPW9PA9XwISACu8nvpPqF0BVo= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f h1:cUMEy+8oS78BWIH9OWazBkzbr090Od9tWBNtZHkOhf0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= @@ -646,8 +648,8 @@ google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= -google.golang.org/grpc v1.66.2 h1:3QdXkuq3Bkh7w+ywLdLvM56cmGvQHUMZpiCzt6Rqaoo= -google.golang.org/grpc v1.66.2/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y= +google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E= +google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= 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= diff --git a/x/epochs/keeper/abci.go b/x/epochs/keeper/abci.go index 33821e7fd92c..4b8ab757dae9 100644 --- a/x/epochs/keeper/abci.go +++ b/x/epochs/keeper/abci.go @@ -11,7 +11,8 @@ import ( // BeginBlocker of epochs module. func (k Keeper) BeginBlocker(ctx context.Context) error { - defer telemetry.ModuleMeasureSince(types.ModuleName, telemetry.Now(), telemetry.MetricKeyBeginBlocker) + start := telemetry.Now() + defer telemetry.ModuleMeasureSince(types.ModuleName, start, telemetry.MetricKeyBeginBlocker) headerInfo := k.HeaderService.HeaderInfo(ctx) err := k.EpochInfo.Walk( diff --git a/x/epochs/keeper/epoch.go b/x/epochs/keeper/epoch.go index 3943cf4c61c5..c655dac54845 100644 --- a/x/epochs/keeper/epoch.go +++ b/x/epochs/keeper/epoch.go @@ -5,8 +5,15 @@ import ( "fmt" "cosmossdk.io/x/epochs/types" + + sdk "github.com/cosmos/cosmos-sdk/types" ) +// GetEpochInfo returns epoch info by identifier. +func (k Keeper) GetEpochInfo(ctx sdk.Context, identifier string) (types.EpochInfo, error) { + return k.EpochInfo.Get(ctx, identifier) +} + // AddEpochInfo adds a new epoch info. Will return an error if the epoch fails validation, // or re-uses an existing identifier. // This method also sets the start time if left unset, and sets the epoch start height. diff --git a/x/epochs/module.go b/x/epochs/module.go index 6930d82174a2..2fba7c0de141 100644 --- a/x/epochs/module.go +++ b/x/epochs/module.go @@ -125,8 +125,3 @@ func (AppModule) GenerateGenesisState(simState *module.SimulationState) { func (am AppModule) RegisterStoreDecoder(sdr simtypes.StoreDecoderRegistry) { sdr[types.StoreKey] = simtypes.NewStoreDecoderFuncFromCollectionsSchema(am.keeper.Schema) } - -// WeightedOperations returns the all the gov module operations with their respective weights. -func (am AppModule) WeightedOperations(simState module.SimulationState) []simtypes.WeightedOperation { - return nil -} diff --git a/x/epochs/simulation/genesis.go b/x/epochs/simulation/genesis.go index c236faacbb8a..8aa17add5bbc 100644 --- a/x/epochs/simulation/genesis.go +++ b/x/epochs/simulation/genesis.go @@ -1,8 +1,6 @@ package simulation import ( - "encoding/json" - "fmt" "math/rand" "strconv" "time" @@ -37,10 +35,5 @@ func RandomizedGenState(simState *module.SimulationState) { Epochs: epochs, } - bz, err := json.MarshalIndent(&epochsGenesis, "", " ") - if err != nil { - panic(err) - } - fmt.Printf("Selected randomly generated epochs parameters:\n%s\n", bz) simState.GenState[types.ModuleName] = simState.Cdc.MustMarshalJSON(&epochsGenesis) } diff --git a/x/evidence/CHANGELOG.md b/x/evidence/CHANGELOG.md index b2e8c9d76acc..fb5ee8a1e34a 100644 --- a/x/evidence/CHANGELOG.md +++ b/x/evidence/CHANGELOG.md @@ -32,6 +32,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ * [#19482](https://github.com/cosmos/cosmos-sdk/pull/19482) `appmodule.Environment` is passed to `NewKeeper` instead of individual services * [#19627](https://github.com/cosmos/cosmos-sdk/pull/19627) `NewAppModule` now takes in a `codec.Codec` as its first argument * [#21480](https://github.com/cosmos/cosmos-sdk/pull/21480) ConsensusKeeper is required to be passed to the keeper. +* [#21859](https://github.com/cosmos/cosmos-sdk/pull/21859) `NewKeeper` now takes in a consensus codec to avoid reliance on staking for decoding addresses. ## [v0.1.1](https://github.com/cosmos/cosmos-sdk/releases/tag/x/evidence/v0.1.1) - 2024-04-22 diff --git a/x/evidence/depinject.go b/x/evidence/depinject.go index ecbbbbde0330..ebd5c7bba40b 100644 --- a/x/evidence/depinject.go +++ b/x/evidence/depinject.go @@ -33,10 +33,11 @@ type ModuleInputs struct { EvidenceHandlers []eviclient.EvidenceHandler `optional:"true"` CometService comet.Service - StakingKeeper types.StakingKeeper - SlashingKeeper types.SlashingKeeper - ConsensusKeeper types.ConsensusKeeper - AddressCodec address.Codec + StakingKeeper types.StakingKeeper + SlashingKeeper types.SlashingKeeper + ConsensusKeeper types.ConsensusKeeper + AddressCodec address.Codec + ConsensusAddressCodec address.Codec } type ModuleOutputs struct { @@ -47,7 +48,7 @@ type ModuleOutputs struct { } func ProvideModule(in ModuleInputs) ModuleOutputs { - k := keeper.NewKeeper(in.Cdc, in.Environment, in.StakingKeeper, in.SlashingKeeper, in.ConsensusKeeper, in.AddressCodec) + k := keeper.NewKeeper(in.Cdc, in.Environment, in.StakingKeeper, in.SlashingKeeper, in.ConsensusKeeper, in.AddressCodec, in.ConsensusAddressCodec) m := NewAppModule(in.Cdc, *k, in.CometService, in.EvidenceHandlers...) return ModuleOutputs{EvidenceKeeper: *k, Module: m} diff --git a/x/evidence/go.mod b/x/evidence/go.mod index df39a5174060..94af124c0a3d 100644 --- a/x/evidence/go.mod +++ b/x/evidence/go.mod @@ -3,10 +3,10 @@ module cosmossdk.io/x/evidence go 1.23.1 require ( - cosmossdk.io/api v0.7.5 + cosmossdk.io/api v0.7.6 cosmossdk.io/collections v0.4.0 - cosmossdk.io/core v1.0.0-alpha.2 - cosmossdk.io/core/testing v0.0.0-00010101000000-000000000000 + cosmossdk.io/core v1.0.0-alpha.4 + cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29 cosmossdk.io/depinject v1.0.0 cosmossdk.io/errors v1.0.1 cosmossdk.io/math v1.3.0 @@ -19,8 +19,8 @@ require ( github.com/grpc-ecosystem/grpc-gateway v1.16.0 github.com/spf13/cobra v1.8.1 github.com/stretchr/testify v1.9.0 - google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 - google.golang.org/grpc v1.66.2 + google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 + google.golang.org/grpc v1.67.1 google.golang.org/protobuf v1.34.2 ) @@ -28,7 +28,7 @@ require ( buf.build/gen/go/cometbft/cometbft/protocolbuffers/go v1.34.2-20240701160653-fedbb9acfd2f.2 // indirect buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.34.2-20240130113600-88ef6483f90f.2 // indirect cosmossdk.io/log v1.4.1 // indirect - cosmossdk.io/schema v0.2.0 // indirect + cosmossdk.io/schema v0.3.1-0.20240930054013-7c6e0388a3f9 // indirect cosmossdk.io/x/bank v0.0.0-20240226161501-23359a0b6d91 // indirect cosmossdk.io/x/staking v0.0.0-00010101000000-000000000000 // indirect cosmossdk.io/x/tx v0.13.3 // indirect @@ -98,7 +98,7 @@ require ( github.com/hashicorp/hcl v1.0.0 // indirect github.com/hashicorp/yamux v0.1.1 // indirect github.com/hdevalence/ed25519consensus v0.2.0 // indirect - github.com/huandu/skiplist v1.2.0 // indirect + github.com/huandu/skiplist v1.2.1 // indirect github.com/iancoleman/strcase v0.3.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jmhodges/levigo v1.0.0 // indirect @@ -121,9 +121,9 @@ require ( github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/client_golang v1.20.3 // indirect + github.com/prometheus/client_golang v1.20.4 // indirect github.com/prometheus/client_model v0.6.1 // indirect - github.com/prometheus/common v0.59.1 // indirect + github.com/prometheus/common v0.60.0 // indirect github.com/prometheus/procfs v0.15.1 // indirect github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect github.com/rogpeppe/go-internal v1.12.0 // indirect @@ -159,7 +159,7 @@ require ( golang.org/x/text v0.18.0 // indirect golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect gotest.tools/v3 v3.5.1 // indirect @@ -172,7 +172,6 @@ replace github.com/cosmos/cosmos-sdk => ../../. // TODO remove post spinning out all modules replace ( cosmossdk.io/api => ../../api - cosmossdk.io/core/testing => ../../core/testing cosmossdk.io/store => ../../store cosmossdk.io/x/bank => ../bank cosmossdk.io/x/staking => ../staking diff --git a/x/evidence/go.sum b/x/evidence/go.sum index a658644fd79f..c9df997e10ec 100644 --- a/x/evidence/go.sum +++ b/x/evidence/go.sum @@ -6,8 +6,10 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cosmossdk.io/collections v0.4.0 h1:PFmwj2W8szgpD5nOd8GWH6AbYNi1f2J6akWXJ7P5t9s= cosmossdk.io/collections v0.4.0/go.mod h1:oa5lUING2dP+gdDquow+QjlF45eL1t4TJDypgGd+tv0= -cosmossdk.io/core v1.0.0-alpha.2 h1:epU0Xwces4Rgl5bMhHHkXGaGDcyucNGlC/JDH+Suckg= -cosmossdk.io/core v1.0.0-alpha.2/go.mod h1:abgLjeFLhtuKIYZWSPlVUgQBrKObO7ULV35KYfexE90= +cosmossdk.io/core v1.0.0-alpha.4 h1:9iuroT9ejDYETCsGkzkvs/wAY/5UFl7nCIINFRxyMJY= +cosmossdk.io/core v1.0.0-alpha.4/go.mod h1:3u9cWq1FAVtiiCrDPpo4LhR+9V6k/ycSG4/Y/tREWCY= +cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29 h1:NxxUo0GMJUbIuVg0R70e3cbn9eFTEuMr7ev1AFvypdY= +cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29/go.mod h1:8s2tPeJtSiQuoyPmr2Ag7meikonISO4Fv4MoO8+ORrs= cosmossdk.io/depinject v1.0.0 h1:dQaTu6+O6askNXO06+jyeUAnF2/ssKwrrszP9t5q050= cosmossdk.io/depinject v1.0.0/go.mod h1:zxK/h3HgHoA/eJVtiSsoaRaRA2D5U4cJ5thIG4ssbB8= cosmossdk.io/errors v1.0.1 h1:bzu+Kcr0kS/1DuPBtUFdWjzLqyUuCiyHjyJB6srBV/0= @@ -16,8 +18,8 @@ cosmossdk.io/log v1.4.1 h1:wKdjfDRbDyZRuWa8M+9nuvpVYxrEOwbD/CA8hvhU8QM= cosmossdk.io/log v1.4.1/go.mod h1:k08v0Pyq+gCP6phvdI6RCGhLf/r425UT6Rk/m+o74rU= cosmossdk.io/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE= cosmossdk.io/math v1.3.0/go.mod h1:vnRTxewy+M7BtXBNFybkuhSH4WfedVAAnERHgVFhp3k= -cosmossdk.io/schema v0.2.0 h1:UH5CR1DqUq8yP+5Np8PbvG4YX0zAUsTN2Qk6yThmfMk= -cosmossdk.io/schema v0.2.0/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= +cosmossdk.io/schema v0.3.1-0.20240930054013-7c6e0388a3f9 h1:DmOoS/1PeY6Ih0hAVlJ69kLMUrLV+TCbfICrZtB1vdU= +cosmossdk.io/schema v0.3.1-0.20240930054013-7c6e0388a3f9/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMbk2FiG/kXiLl8BRyzTWDw7gX/Hz7Dd5eDMs= @@ -292,8 +294,8 @@ github.com/hdevalence/ed25519consensus v0.2.0/go.mod h1:w3BHWjwJbFU29IRHL1Iqkw3s github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/huandu/go-assert v1.1.5 h1:fjemmA7sSfYHJD7CUqs9qTwwfdNAx7/j2/ZlHXzNB3c= github.com/huandu/go-assert v1.1.5/go.mod h1:yOLvuqZwmcHIC5rIzrBhT7D3Q9c3GFnd0JrPVhn/06U= -github.com/huandu/skiplist v1.2.0 h1:gox56QD77HzSC0w+Ws3MH3iie755GBJU1OER3h5VsYw= -github.com/huandu/skiplist v1.2.0/go.mod h1:7v3iFjLcSAzO4fN5B8dvebvo/qsfumiLiDXMrPiHF9w= +github.com/huandu/skiplist v1.2.1 h1:dTi93MgjwErA/8idWTzIw4Y1kZsMWx35fmI2c8Rij7w= +github.com/huandu/skiplist v1.2.1/go.mod h1:7v3iFjLcSAzO4fN5B8dvebvo/qsfumiLiDXMrPiHF9w= github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI= github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= @@ -402,8 +404,8 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= -github.com/prometheus/client_golang v1.20.3 h1:oPksm4K8B+Vt35tUhw6GbSNSgVlVSBH0qELP/7u83l4= -github.com/prometheus/client_golang v1.20.3/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_golang v1.20.4 h1:Tgh3Yr67PaOv/uTqloMsCEdeuFTatm5zIq5+qNN23vI= +github.com/prometheus/client_golang v1.20.4/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -412,8 +414,8 @@ github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= -github.com/prometheus/common v0.59.1 h1:LXb1quJHWm1P6wq/U824uxYi4Sg0oGvNeUm1z5dJoX0= -github.com/prometheus/common v0.59.1/go.mod h1:GpWM7dewqmVYcd7SmRaiWVe9SSqjf0UrwnYnpEZNuT0= +github.com/prometheus/common v0.60.0 h1:+V9PAREWNvJMAuJ1x1BaWl9dewMW4YrHZQbx0sJNllA= +github.com/prometheus/common v0.60.0/go.mod h1:h0LYf1R1deLSKtD4Vdg8gy4RuOvENW2J/h19V5NADQw= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/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= @@ -636,10 +638,10 @@ google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEY google.golang.org/genproto v0.0.0-20220314164441-57ef72a4c106/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E= google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de h1:F6qOa9AZTYJXOUEr4jDysRDLrm4PHePlge4v4TGAlxY= google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:VUhTRKeHn9wwcdrk73nvdC9gF178Tzhmt/qyaFcPLSo= -google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 h1:+rdxYoE3E5htTEWIe15GlN6IfvbURM//Jt0mmkmm6ZU= -google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117/go.mod h1:OimBR/bc1wPO9iV4NC2bpyjy3VnAwZh5EBPQdtaE5oo= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:pPJltXNxVzT4pK9yD8vR9X75DaWYYmLGMsEvBfFQZzQ= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= +google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 h1:wKguEg1hsxI2/L3hUYrpo1RVi48K+uTyzKqprwLXsb8= +google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142/go.mod h1:d6be+8HhtEtucleCbxpPW9PA9XwISACu8nvpPqF0BVo= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f h1:cUMEy+8oS78BWIH9OWazBkzbr090Od9tWBNtZHkOhf0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= @@ -650,8 +652,8 @@ google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= -google.golang.org/grpc v1.66.2 h1:3QdXkuq3Bkh7w+ywLdLvM56cmGvQHUMZpiCzt6Rqaoo= -google.golang.org/grpc v1.66.2/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y= +google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E= +google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= 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= diff --git a/x/evidence/keeper/abci.go b/x/evidence/keeper/abci.go index 86dbd78adf36..a39b4b3e5e91 100644 --- a/x/evidence/keeper/abci.go +++ b/x/evidence/keeper/abci.go @@ -13,7 +13,8 @@ import ( // BeginBlocker iterates through and handles any newly discovered evidence of // misbehavior submitted by CometBFT. Currently, only equivocation is handled. func (k Keeper) BeginBlocker(ctx context.Context, cometService comet.Service) error { - defer telemetry.ModuleMeasureSince(types.ModuleName, telemetry.Now(), telemetry.MetricKeyBeginBlocker) + start := telemetry.Now() + defer telemetry.ModuleMeasureSince(types.ModuleName, start, telemetry.MetricKeyBeginBlocker) bi := cometService.CometInfo(ctx) @@ -23,7 +24,7 @@ func (k Keeper) BeginBlocker(ctx context.Context, cometService comet.Service) er // It's still ongoing discussion how should we treat and slash attacks with // premeditation. So for now we agree to treat them in the same way. case comet.LightClientAttack, comet.DuplicateVote: - evidence := types.FromABCIEvidence(evidence, k.stakingKeeper.ConsensusAddressCodec()) + evidence := types.FromABCIEvidence(evidence, k.consensusAddressCodec) err := k.handleEquivocationEvidence(ctx, evidence) if err != nil { return err diff --git a/x/evidence/keeper/infraction.go b/x/evidence/keeper/infraction.go index bfb5e95ed1a8..98482358cc05 100644 --- a/x/evidence/keeper/infraction.go +++ b/x/evidence/keeper/infraction.go @@ -10,7 +10,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" ) -// HandleEquivocationEvidence implements an equivocation evidence handler. Assuming the +// handleEquivocationEvidence implements an equivocation evidence handler. Assuming the // evidence is valid, the validator committing the misbehavior will be slashed, // jailed and tombstoned. Once tombstoned, the validator will not be able to // recover. Note, the evidence contains the block time and height at the time of @@ -25,7 +25,7 @@ import ( // TODO: Some of the invalid constraints listed above may need to be reconsidered // in the case of a lunatic attack. func (k Keeper) handleEquivocationEvidence(ctx context.Context, evidence *types.Equivocation) error { - consAddr := evidence.GetConsensusAddress(k.stakingKeeper.ConsensusAddressCodec()) + consAddr := evidence.GetConsensusAddress(k.consensusAddressCodec) validator, err := k.stakingKeeper.ValidatorByConsAddr(ctx, consAddr) if err != nil { diff --git a/x/evidence/keeper/keeper.go b/x/evidence/keeper/keeper.go index 8cab89fbdd0e..954fc18c5e18 100644 --- a/x/evidence/keeper/keeper.go +++ b/x/evidence/keeper/keeper.go @@ -23,12 +23,13 @@ import ( type Keeper struct { appmodule.Environment - cdc codec.BinaryCodec - router types.Router - stakingKeeper types.StakingKeeper - slashingKeeper types.SlashingKeeper - consensusKeeper types.ConsensusKeeper - addressCodec address.Codec + cdc codec.BinaryCodec + router types.Router + stakingKeeper types.StakingKeeper + slashingKeeper types.SlashingKeeper + consensusKeeper types.ConsensusKeeper + addressCodec address.Codec + consensusAddressCodec address.Codec Schema collections.Schema // Evidences key: evidence hash bytes | value: Evidence @@ -38,17 +39,18 @@ type Keeper struct { // NewKeeper creates a new Keeper object. func NewKeeper( cdc codec.BinaryCodec, env appmodule.Environment, stakingKeeper types.StakingKeeper, - slashingKeeper types.SlashingKeeper, ck types.ConsensusKeeper, ac address.Codec, + slashingKeeper types.SlashingKeeper, ck types.ConsensusKeeper, ac, consensusAddressCodec address.Codec, ) *Keeper { sb := collections.NewSchemaBuilder(env.KVStoreService) k := &Keeper{ - Environment: env, - cdc: cdc, - stakingKeeper: stakingKeeper, - slashingKeeper: slashingKeeper, - consensusKeeper: ck, - addressCodec: ac, - Evidences: collections.NewMap(sb, types.KeyPrefixEvidence, "evidences", collections.BytesKey, codec.CollInterfaceValue[exported.Evidence](cdc)), + Environment: env, + cdc: cdc, + stakingKeeper: stakingKeeper, + slashingKeeper: slashingKeeper, + consensusKeeper: ck, + addressCodec: ac, + consensusAddressCodec: consensusAddressCodec, + Evidences: collections.NewMap(sb, types.KeyPrefixEvidence, "evidences", collections.BytesKey, codec.CollInterfaceValue[exported.Evidence](cdc)), } schema, err := sb.Build() if err != nil { diff --git a/x/evidence/keeper/keeper_test.go b/x/evidence/keeper/keeper_test.go index 6820bb826511..0113c9deaa28 100644 --- a/x/evidence/keeper/keeper_test.go +++ b/x/evidence/keeper/keeper_test.go @@ -111,6 +111,7 @@ func (suite *KeeperTestSuite) SetupTest() { slashingKeeper, ck, address.NewBech32Codec("cosmos"), + address.NewBech32Codec("cosmosvalcons"), ) suite.stakingKeeper = stakingKeeper diff --git a/x/evidence/keeper/msg_server_test.go b/x/evidence/keeper/msg_server_test.go index 86ac3447dcaa..fdc3b78d3cbf 100644 --- a/x/evidence/keeper/msg_server_test.go +++ b/x/evidence/keeper/msg_server_test.go @@ -70,7 +70,6 @@ func (s *KeeperTestSuite) TestSubmitEvidence() { } for _, tc := range testCases { - tc := tc s.Run(tc.name, func() { _, err := s.msgServer.SubmitEvidence(s.ctx, tc.req) if tc.expErr { diff --git a/x/evidence/module.go b/x/evidence/module.go index 513563aec10d..0327a83915ef 100644 --- a/x/evidence/module.go +++ b/x/evidence/module.go @@ -152,8 +152,3 @@ func (AppModule) GenerateGenesisState(simState *module.SimulationState) { func (am AppModule) RegisterStoreDecoder(sdr simtypes.StoreDecoderRegistry) { sdr[types.StoreKey] = simtypes.NewStoreDecoderFuncFromCollectionsSchema(am.keeper.Schema) } - -// WeightedOperations returns the all the gov module operations with their respective weights. -func (am AppModule) WeightedOperations(simState module.SimulationState) []simtypes.WeightedOperation { - return nil -} diff --git a/x/evidence/simulation/genesis.go b/x/evidence/simulation/genesis.go index 24b956274695..d4a329d203bb 100644 --- a/x/evidence/simulation/genesis.go +++ b/x/evidence/simulation/genesis.go @@ -1,8 +1,6 @@ package simulation import ( - "encoding/json" - "fmt" "math/rand" "cosmossdk.io/x/evidence/exported" @@ -28,10 +26,5 @@ func RandomizedGenState(simState *module.SimulationState) { evidenceGenesis := types.NewGenesisState(ev) - bz, err := json.MarshalIndent(&evidenceGenesis, "", " ") - if err != nil { - panic(err) - } - fmt.Printf("Selected randomly generated %s parameters:\n%s\n", types.ModuleName, bz) simState.GenState[types.ModuleName] = simState.Cdc.MustMarshalJSON(evidenceGenesis) } diff --git a/x/evidence/testutil/expected_keepers_mocks.go b/x/evidence/testutil/expected_keepers_mocks.go index eb6c0f2785ad..b9efeb2f1385 100644 --- a/x/evidence/testutil/expected_keepers_mocks.go +++ b/x/evidence/testutil/expected_keepers_mocks.go @@ -10,7 +10,6 @@ import ( time "time" stakingv1beta1 "cosmossdk.io/api/cosmos/staking/v1beta1" - address "cosmossdk.io/core/address" math "cosmossdk.io/math" types "github.com/cosmos/cosmos-sdk/crypto/types" types0 "github.com/cosmos/cosmos-sdk/types" @@ -40,20 +39,6 @@ func (m *MockStakingKeeper) EXPECT() *MockStakingKeeperMockRecorder { return m.recorder } -// ConsensusAddressCodec mocks base method. -func (m *MockStakingKeeper) ConsensusAddressCodec() address.Codec { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "ConsensusAddressCodec") - ret0, _ := ret[0].(address.Codec) - return ret0 -} - -// ConsensusAddressCodec indicates an expected call of ConsensusAddressCodec. -func (mr *MockStakingKeeperMockRecorder) ConsensusAddressCodec() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ConsensusAddressCodec", reflect.TypeOf((*MockStakingKeeper)(nil).ConsensusAddressCodec)) -} - // ValidatorByConsAddr mocks base method. func (m *MockStakingKeeper) ValidatorByConsAddr(arg0 context.Context, arg1 types0.ConsAddress) (types0.ValidatorI, error) { m.ctrl.T.Helper() diff --git a/x/evidence/types/evidence_test.go b/x/evidence/types/evidence_test.go index bfa20f82a98d..dd6b31056a70 100644 --- a/x/evidence/types/evidence_test.go +++ b/x/evidence/types/evidence_test.go @@ -70,7 +70,6 @@ func TestEquivocationValidateBasic(t *testing.T) { } for _, tc := range testCases { - tc := tc t.Run(tc.name, func(t *testing.T) { require.Equal(t, tc.expectErr, tc.e.ValidateBasic() != nil) }) diff --git a/x/evidence/types/expected_keepers.go b/x/evidence/types/expected_keepers.go index a7ecdaf2ca38..7cb8486e145d 100644 --- a/x/evidence/types/expected_keepers.go +++ b/x/evidence/types/expected_keepers.go @@ -5,7 +5,6 @@ import ( "time" st "cosmossdk.io/api/cosmos/staking/v1beta1" - "cosmossdk.io/core/address" "cosmossdk.io/math" cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" @@ -15,7 +14,6 @@ import ( // StakingKeeper defines the staking module interface contract needed by the // evidence module. type StakingKeeper interface { - ConsensusAddressCodec() address.Codec ValidatorByConsAddr(context.Context, sdk.ConsAddress) (sdk.ValidatorI, error) } diff --git a/x/feegrant/client/cli/tx_test.go b/x/feegrant/client/cli/tx_test.go index 0759d0752f71..2fcb4020185e 100644 --- a/x/feegrant/client/cli/tx_test.go +++ b/x/feegrant/client/cli/tx_test.go @@ -420,8 +420,6 @@ func (s *CLITestSuite) TestNewCmdFeeGrant() { } for _, tc := range testCases { - tc := tc - s.Run(tc.name, func() { cmd := cli.NewCmdFeeGrant() out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) @@ -624,8 +622,6 @@ func (s *CLITestSuite) TestFilteredFeeAllowance() { } for _, tc := range testCases { - tc := tc - s.Run(tc.name, func() { cmd := cli.NewCmdFeeGrant() out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) @@ -687,8 +683,6 @@ func (s *CLITestSuite) TestFilteredFeeAllowance() { } for _, tc := range cases { - tc := tc - s.Run(tc.name, func() { err := tc.malleate() s.Require().NoError(err) diff --git a/x/feegrant/go.mod b/x/feegrant/go.mod index 6ce3c7e54836..56310d95579a 100644 --- a/x/feegrant/go.mod +++ b/x/feegrant/go.mod @@ -3,10 +3,10 @@ module cosmossdk.io/x/feegrant go 1.23.1 require ( - cosmossdk.io/api v0.7.5 + cosmossdk.io/api v0.7.6 cosmossdk.io/collections v0.4.0 - cosmossdk.io/core v1.0.0-alpha.2 - cosmossdk.io/core/testing v0.0.0-00010101000000-000000000000 + cosmossdk.io/core v1.0.0-alpha.4 + cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29 cosmossdk.io/depinject v1.0.0 cosmossdk.io/errors v1.0.1 cosmossdk.io/math v1.3.0 @@ -22,8 +22,8 @@ require ( github.com/grpc-ecosystem/grpc-gateway v1.16.0 github.com/spf13/cobra v1.8.1 github.com/stretchr/testify v1.9.0 - google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 - google.golang.org/grpc v1.66.2 + google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 + google.golang.org/grpc v1.67.1 google.golang.org/protobuf v1.34.2 gotest.tools/v3 v3.5.1 ) @@ -37,7 +37,7 @@ require ( buf.build/gen/go/cometbft/cometbft/protocolbuffers/go v1.34.2-20240701160653-fedbb9acfd2f.2 // indirect buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.34.2-20240130113600-88ef6483f90f.2 // indirect cosmossdk.io/log v1.4.1 // indirect - cosmossdk.io/schema v0.2.0 // indirect + cosmossdk.io/schema v0.3.1-0.20240930054013-7c6e0388a3f9 // indirect cosmossdk.io/x/protocolpool v0.0.0-20230925135524-a1bc045b3190 // indirect cosmossdk.io/x/staking v0.0.0-00010101000000-000000000000 // indirect cosmossdk.io/x/tx v0.13.3 // indirect @@ -105,7 +105,7 @@ require ( github.com/hashicorp/hcl v1.0.0 // indirect github.com/hashicorp/yamux v0.1.1 // indirect github.com/hdevalence/ed25519consensus v0.2.0 // indirect - github.com/huandu/skiplist v1.2.0 // indirect + github.com/huandu/skiplist v1.2.1 // indirect github.com/iancoleman/strcase v0.3.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jmhodges/levigo v1.0.0 // indirect @@ -129,9 +129,9 @@ require ( github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/client_golang v1.20.3 // indirect + github.com/prometheus/client_golang v1.20.4 // indirect github.com/prometheus/client_model v0.6.1 // indirect - github.com/prometheus/common v0.59.1 // indirect + github.com/prometheus/common v0.60.0 // indirect github.com/prometheus/procfs v0.15.1 // indirect github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect github.com/rogpeppe/go-internal v1.12.0 // indirect @@ -167,7 +167,7 @@ require ( golang.org/x/text v0.18.0 // indirect golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect pgregory.net/rapid v1.1.0 // indirect @@ -180,7 +180,6 @@ replace github.com/cosmos/cosmos-sdk => ../../. replace ( cosmossdk.io/api => ../../api cosmossdk.io/collections => ../../collections - cosmossdk.io/core/testing => ../../core/testing cosmossdk.io/store => ../../store cosmossdk.io/x/bank => ../bank cosmossdk.io/x/gov => ../gov diff --git a/x/feegrant/go.sum b/x/feegrant/go.sum index 59aa48e27918..8e11511b6d57 100644 --- a/x/feegrant/go.sum +++ b/x/feegrant/go.sum @@ -4,8 +4,10 @@ buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.34.2-20240130113600-88e buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.34.2-20240130113600-88ef6483f90f.2/go.mod h1:HqcXMSa5qnNuakaMUo+hWhF51mKbcrZxGl9Vp5EeJXc= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cosmossdk.io/core v1.0.0-alpha.2 h1:epU0Xwces4Rgl5bMhHHkXGaGDcyucNGlC/JDH+Suckg= -cosmossdk.io/core v1.0.0-alpha.2/go.mod h1:abgLjeFLhtuKIYZWSPlVUgQBrKObO7ULV35KYfexE90= +cosmossdk.io/core v1.0.0-alpha.4 h1:9iuroT9ejDYETCsGkzkvs/wAY/5UFl7nCIINFRxyMJY= +cosmossdk.io/core v1.0.0-alpha.4/go.mod h1:3u9cWq1FAVtiiCrDPpo4LhR+9V6k/ycSG4/Y/tREWCY= +cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29 h1:NxxUo0GMJUbIuVg0R70e3cbn9eFTEuMr7ev1AFvypdY= +cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29/go.mod h1:8s2tPeJtSiQuoyPmr2Ag7meikonISO4Fv4MoO8+ORrs= cosmossdk.io/depinject v1.0.0 h1:dQaTu6+O6askNXO06+jyeUAnF2/ssKwrrszP9t5q050= cosmossdk.io/depinject v1.0.0/go.mod h1:zxK/h3HgHoA/eJVtiSsoaRaRA2D5U4cJ5thIG4ssbB8= cosmossdk.io/errors v1.0.1 h1:bzu+Kcr0kS/1DuPBtUFdWjzLqyUuCiyHjyJB6srBV/0= @@ -14,8 +16,8 @@ cosmossdk.io/log v1.4.1 h1:wKdjfDRbDyZRuWa8M+9nuvpVYxrEOwbD/CA8hvhU8QM= cosmossdk.io/log v1.4.1/go.mod h1:k08v0Pyq+gCP6phvdI6RCGhLf/r425UT6Rk/m+o74rU= cosmossdk.io/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE= cosmossdk.io/math v1.3.0/go.mod h1:vnRTxewy+M7BtXBNFybkuhSH4WfedVAAnERHgVFhp3k= -cosmossdk.io/schema v0.2.0 h1:UH5CR1DqUq8yP+5Np8PbvG4YX0zAUsTN2Qk6yThmfMk= -cosmossdk.io/schema v0.2.0/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= +cosmossdk.io/schema v0.3.1-0.20240930054013-7c6e0388a3f9 h1:DmOoS/1PeY6Ih0hAVlJ69kLMUrLV+TCbfICrZtB1vdU= +cosmossdk.io/schema v0.3.1-0.20240930054013-7c6e0388a3f9/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= cosmossdk.io/x/protocolpool v0.0.0-20230925135524-a1bc045b3190 h1:XQJj9Dv9Gtze0l2TF79BU5lkP6MkUveTUuKICmxoz+o= cosmossdk.io/x/protocolpool v0.0.0-20230925135524-a1bc045b3190/go.mod h1:7WUGupOvmlHJoIMBz1JbObQxeo6/TDiuDBxmtod8HRg= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= @@ -298,8 +300,8 @@ github.com/hdevalence/ed25519consensus v0.2.0/go.mod h1:w3BHWjwJbFU29IRHL1Iqkw3s github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/huandu/go-assert v1.1.5 h1:fjemmA7sSfYHJD7CUqs9qTwwfdNAx7/j2/ZlHXzNB3c= github.com/huandu/go-assert v1.1.5/go.mod h1:yOLvuqZwmcHIC5rIzrBhT7D3Q9c3GFnd0JrPVhn/06U= -github.com/huandu/skiplist v1.2.0 h1:gox56QD77HzSC0w+Ws3MH3iie755GBJU1OER3h5VsYw= -github.com/huandu/skiplist v1.2.0/go.mod h1:7v3iFjLcSAzO4fN5B8dvebvo/qsfumiLiDXMrPiHF9w= +github.com/huandu/skiplist v1.2.1 h1:dTi93MgjwErA/8idWTzIw4Y1kZsMWx35fmI2c8Rij7w= +github.com/huandu/skiplist v1.2.1/go.mod h1:7v3iFjLcSAzO4fN5B8dvebvo/qsfumiLiDXMrPiHF9w= github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI= github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= @@ -410,8 +412,8 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= -github.com/prometheus/client_golang v1.20.3 h1:oPksm4K8B+Vt35tUhw6GbSNSgVlVSBH0qELP/7u83l4= -github.com/prometheus/client_golang v1.20.3/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_golang v1.20.4 h1:Tgh3Yr67PaOv/uTqloMsCEdeuFTatm5zIq5+qNN23vI= +github.com/prometheus/client_golang v1.20.4/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -420,8 +422,8 @@ github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= -github.com/prometheus/common v0.59.1 h1:LXb1quJHWm1P6wq/U824uxYi4Sg0oGvNeUm1z5dJoX0= -github.com/prometheus/common v0.59.1/go.mod h1:GpWM7dewqmVYcd7SmRaiWVe9SSqjf0UrwnYnpEZNuT0= +github.com/prometheus/common v0.60.0 h1:+V9PAREWNvJMAuJ1x1BaWl9dewMW4YrHZQbx0sJNllA= +github.com/prometheus/common v0.60.0/go.mod h1:h0LYf1R1deLSKtD4Vdg8gy4RuOvENW2J/h19V5NADQw= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/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= @@ -646,10 +648,10 @@ google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEY google.golang.org/genproto v0.0.0-20220314164441-57ef72a4c106/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E= google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de h1:F6qOa9AZTYJXOUEr4jDysRDLrm4PHePlge4v4TGAlxY= google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:VUhTRKeHn9wwcdrk73nvdC9gF178Tzhmt/qyaFcPLSo= -google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 h1:+rdxYoE3E5htTEWIe15GlN6IfvbURM//Jt0mmkmm6ZU= -google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117/go.mod h1:OimBR/bc1wPO9iV4NC2bpyjy3VnAwZh5EBPQdtaE5oo= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:pPJltXNxVzT4pK9yD8vR9X75DaWYYmLGMsEvBfFQZzQ= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= +google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 h1:wKguEg1hsxI2/L3hUYrpo1RVi48K+uTyzKqprwLXsb8= +google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142/go.mod h1:d6be+8HhtEtucleCbxpPW9PA9XwISACu8nvpPqF0BVo= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f h1:cUMEy+8oS78BWIH9OWazBkzbr090Od9tWBNtZHkOhf0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= @@ -660,8 +662,8 @@ google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= -google.golang.org/grpc v1.66.2 h1:3QdXkuq3Bkh7w+ywLdLvM56cmGvQHUMZpiCzt6Rqaoo= -google.golang.org/grpc v1.66.2/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y= +google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E= +google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= 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= diff --git a/x/feegrant/grant_test.go b/x/feegrant/grant_test.go index a333a51e7756..4880b6eb3cf0 100644 --- a/x/feegrant/grant_test.go +++ b/x/feegrant/grant_test.go @@ -81,7 +81,6 @@ func TestGrant(t *testing.T) { } for name, tc := range cases { - tc := tc t.Run(name, func(t *testing.T) { granterStr, err := addressCodec.BytesToString(tc.granter) require.NoError(t, err) diff --git a/x/feegrant/keeper/genesis_test.go b/x/feegrant/keeper/genesis_test.go index 61cb5cd14a0c..dd2a1eb27bfc 100644 --- a/x/feegrant/keeper/genesis_test.go +++ b/x/feegrant/keeper/genesis_test.go @@ -144,7 +144,6 @@ func TestInitGenesis(t *testing.T) { } for _, tc := range testCases { - tc := tc t.Run(tc.name, func(t *testing.T) { f := initFixture(t) if !tc.invalidAddr { diff --git a/x/feegrant/module/depinject.go b/x/feegrant/module/depinject.go index 018b09d3d593..613d51a14743 100644 --- a/x/feegrant/module/depinject.go +++ b/x/feegrant/module/depinject.go @@ -7,9 +7,13 @@ import ( "cosmossdk.io/depinject/appconfig" "cosmossdk.io/x/feegrant" "cosmossdk.io/x/feegrant/keeper" + "cosmossdk.io/x/feegrant/simulation" "github.com/cosmos/cosmos-sdk/codec" cdctypes "github.com/cosmos/cosmos-sdk/codec/types" + "github.com/cosmos/cosmos-sdk/simsx" + "github.com/cosmos/cosmos-sdk/types/module" + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" ) var _ depinject.OnePerModuleType = AppModule{} @@ -35,6 +39,23 @@ type FeegrantInputs struct { func ProvideModule(in FeegrantInputs) (keeper.Keeper, appmodule.AppModule) { k := keeper.NewKeeper(in.Environment, in.Cdc, in.AccountKeeper) - m := NewAppModule(in.Cdc, in.AccountKeeper, in.BankKeeper, k, in.Registry) + m := NewAppModule(in.Cdc, k, in.Registry) return k, m } + +// AppModuleSimulation functions + +// GenerateGenesisState creates a randomized GenState of the feegrant module. +func (AppModule) GenerateGenesisState(simState *module.SimulationState) { + simulation.RandomizedGenState(simState) +} + +// RegisterStoreDecoder registers a decoder for feegrant module's types +func (am AppModule) RegisterStoreDecoder(sdr simtypes.StoreDecoderRegistry) { + sdr[feegrant.StoreKey] = simulation.NewDecodeStore(am.cdc) +} + +func (am AppModule) WeightedOperationsX(weights simsx.WeightSource, reg simsx.Registry) { + reg.Add(weights.Get("msg_grant_fee_allowance", 100), simulation.MsgGrantAllowanceFactory(am.keeper)) + reg.Add(weights.Get("msg_grant_revoke_allowance", 100), simulation.MsgRevokeAllowanceFactory(am.keeper)) +} diff --git a/x/feegrant/module/module.go b/x/feegrant/module/module.go index c6c79fa396e3..2e22fef937bc 100644 --- a/x/feegrant/module/module.go +++ b/x/feegrant/module/module.go @@ -15,13 +15,11 @@ import ( "cosmossdk.io/x/feegrant" "cosmossdk.io/x/feegrant/client/cli" "cosmossdk.io/x/feegrant/keeper" - "cosmossdk.io/x/feegrant/simulation" sdkclient "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/codec" cdctypes "github.com/cosmos/cosmos-sdk/codec/types" "github.com/cosmos/cosmos-sdk/types/module" - simtypes "github.com/cosmos/cosmos-sdk/types/simulation" ) var ( @@ -41,19 +39,15 @@ type AppModule struct { cdc codec.Codec registry cdctypes.InterfaceRegistry - keeper keeper.Keeper - accountKeeper feegrant.AccountKeeper - bankKeeper feegrant.BankKeeper + keeper keeper.Keeper } // NewAppModule creates a new AppModule object -func NewAppModule(cdc codec.Codec, ak feegrant.AccountKeeper, bk feegrant.BankKeeper, keeper keeper.Keeper, registry cdctypes.InterfaceRegistry) AppModule { +func NewAppModule(cdc codec.Codec, keeper keeper.Keeper, registry cdctypes.InterfaceRegistry) AppModule { return AppModule{ - cdc: cdc, - keeper: keeper, - accountKeeper: ak, - bankKeeper: bk, - registry: registry, + cdc: cdc, + keeper: keeper, + registry: registry, } } @@ -153,23 +147,3 @@ func (AppModule) ConsensusVersion() uint64 { return 2 } func (am AppModule) EndBlock(ctx context.Context) error { return EndBlocker(ctx, am.keeper) } - -// AppModuleSimulation functions - -// GenerateGenesisState creates a randomized GenState of the feegrant module. -func (AppModule) GenerateGenesisState(simState *module.SimulationState) { - simulation.RandomizedGenState(simState) -} - -// RegisterStoreDecoder registers a decoder for feegrant module's types -func (am AppModule) RegisterStoreDecoder(sdr simtypes.StoreDecoderRegistry) { - sdr[feegrant.StoreKey] = simulation.NewDecodeStore(am.cdc) -} - -// WeightedOperations returns all the feegrant module operations with their respective weights. -func (am AppModule) WeightedOperations(simState module.SimulationState) []simtypes.WeightedOperation { - return simulation.WeightedOperations( - simState.AppParams, simState.TxConfig, - am.accountKeeper, am.bankKeeper, am.keeper, - ) -} diff --git a/x/feegrant/simulation/decoder_test.go b/x/feegrant/simulation/decoder_test.go index f29fa98977ad..03d7d1a674c2 100644 --- a/x/feegrant/simulation/decoder_test.go +++ b/x/feegrant/simulation/decoder_test.go @@ -61,7 +61,6 @@ func TestDecodeStore(t *testing.T) { } for i, tt := range tests { - i, tt := i, tt t.Run(tt.name, func(t *testing.T) { switch i { case len(tests) - 1: diff --git a/x/feegrant/simulation/msg_factory.go b/x/feegrant/simulation/msg_factory.go new file mode 100644 index 000000000000..fd8bacb88745 --- /dev/null +++ b/x/feegrant/simulation/msg_factory.go @@ -0,0 +1,58 @@ +package simulation + +import ( + "context" + + "cosmossdk.io/x/feegrant" + "cosmossdk.io/x/feegrant/keeper" + + "github.com/cosmos/cosmos-sdk/simsx" +) + +func MsgGrantAllowanceFactory(k keeper.Keeper) simsx.SimMsgFactoryFn[*feegrant.MsgGrantAllowance] { + return func(ctx context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter) ([]simsx.SimAccount, *feegrant.MsgGrantAllowance) { + granter := testData.AnyAccount(reporter, simsx.WithSpendableBalance()) + grantee := testData.AnyAccount(reporter, simsx.ExcludeAccounts(granter)) + if reporter.IsSkipped() { + return nil, nil + } + if f, _ := k.GetAllowance(ctx, granter.Address, grantee.Address); f != nil { + reporter.Skip("fee allowance exists") + return nil, nil + } + + coins := granter.LiquidBalance().RandSubsetCoins(reporter, simsx.WithSendEnabledCoins()) + oneYear := simsx.BlockTime(ctx).AddDate(1, 0, 0) + msg, err := feegrant.NewMsgGrantAllowance( + &feegrant.BasicAllowance{SpendLimit: coins, Expiration: &oneYear}, + granter.AddressBech32, + grantee.AddressBech32, + ) + if err != nil { + reporter.Skip(err.Error()) + return nil, nil + } + return []simsx.SimAccount{granter}, msg + } +} + +func MsgRevokeAllowanceFactory(k keeper.Keeper) simsx.SimMsgFactoryFn[*feegrant.MsgRevokeAllowance] { + return func(ctx context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter) ([]simsx.SimAccount, *feegrant.MsgRevokeAllowance) { + var gotGrant *feegrant.Grant + if err := k.IterateAllFeeAllowances(ctx, func(grant feegrant.Grant) bool { + gotGrant = &grant + return true + }); err != nil { + reporter.Skip(err.Error()) + return nil, nil + } + if gotGrant == nil { + reporter.Skip("no grant found") + return nil, nil + } + granter := testData.GetAccount(reporter, gotGrant.Granter) + grantee := testData.GetAccount(reporter, gotGrant.Grantee) + msg := feegrant.NewMsgRevokeAllowance(granter.AddressBech32, grantee.AddressBech32) + return []simsx.SimAccount{granter}, &msg + } +} diff --git a/x/feegrant/simulation/operations.go b/x/feegrant/simulation/operations.go deleted file mode 100644 index 65bd53d528e9..000000000000 --- a/x/feegrant/simulation/operations.go +++ /dev/null @@ -1,197 +0,0 @@ -package simulation - -import ( - "math/rand" - - "cosmossdk.io/x/feegrant" - "cosmossdk.io/x/feegrant/keeper" - - "github.com/cosmos/cosmos-sdk/client" - sdk "github.com/cosmos/cosmos-sdk/types" - simtypes "github.com/cosmos/cosmos-sdk/types/simulation" - "github.com/cosmos/cosmos-sdk/x/simulation" -) - -// Simulation operation weights constants -const ( - OpWeightMsgGrantAllowance = "op_weight_msg_grant_fee_allowance" - OpWeightMsgRevokeAllowance = "op_weight_msg_grant_revoke_allowance" - DefaultWeightGrantAllowance int = 100 - DefaultWeightRevokeAllowance int = 100 -) - -var ( - TypeMsgGrantAllowance = sdk.MsgTypeURL(&feegrant.MsgGrantAllowance{}) - TypeMsgRevokeAllowance = sdk.MsgTypeURL(&feegrant.MsgRevokeAllowance{}) -) - -func WeightedOperations( - appParams simtypes.AppParams, - txConfig client.TxConfig, - ak feegrant.AccountKeeper, - bk feegrant.BankKeeper, - k keeper.Keeper, -) simulation.WeightedOperations { - var ( - weightMsgGrantAllowance int - weightMsgRevokeAllowance int - ) - - appParams.GetOrGenerate(OpWeightMsgGrantAllowance, &weightMsgGrantAllowance, nil, - func(_ *rand.Rand) { - weightMsgGrantAllowance = DefaultWeightGrantAllowance - }, - ) - - appParams.GetOrGenerate(OpWeightMsgRevokeAllowance, &weightMsgRevokeAllowance, nil, - func(_ *rand.Rand) { - weightMsgRevokeAllowance = DefaultWeightRevokeAllowance - }, - ) - - return simulation.WeightedOperations{ - simulation.NewWeightedOperation( - weightMsgGrantAllowance, - SimulateMsgGrantAllowance(txConfig, ak, bk, k), - ), - simulation.NewWeightedOperation( - weightMsgRevokeAllowance, - SimulateMsgRevokeAllowance(txConfig, ak, bk, k), - ), - } -} - -// SimulateMsgGrantAllowance generates MsgGrantAllowance with random values. -func SimulateMsgGrantAllowance( - txConfig client.TxConfig, - ak feegrant.AccountKeeper, - bk feegrant.BankKeeper, - k keeper.Keeper, -) simtypes.Operation { - return func( - r *rand.Rand, app simtypes.AppEntrypoint, ctx sdk.Context, accs []simtypes.Account, chainID string, - ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { - granter, _ := simtypes.RandomAcc(r, accs) - grantee, _ := simtypes.RandomAcc(r, accs) - granterStr, err := ak.AddressCodec().BytesToString(granter.Address) - if err != nil { - return simtypes.OperationMsg{}, nil, err - } - granteeStr, err := ak.AddressCodec().BytesToString(grantee.Address) - if err != nil { - return simtypes.OperationMsg{}, nil, err - } - - if granteeStr == granterStr { - return simtypes.NoOpMsg(feegrant.ModuleName, TypeMsgGrantAllowance, "grantee and granter cannot be same"), nil, nil - } - - if f, _ := k.GetAllowance(ctx, granter.Address, grantee.Address); f != nil { - return simtypes.NoOpMsg(feegrant.ModuleName, TypeMsgGrantAllowance, "fee allowance exists"), nil, nil - } - - account := ak.GetAccount(ctx, granter.Address) - - spendableCoins := bk.SpendableCoins(ctx, account.GetAddress()) - if spendableCoins.Empty() { - return simtypes.NoOpMsg(feegrant.ModuleName, TypeMsgGrantAllowance, "unable to grant empty coins as SpendLimit"), nil, nil - } - - oneYear := ctx.HeaderInfo().Time.AddDate(1, 0, 0) - msg, err := feegrant.NewMsgGrantAllowance(&feegrant.BasicAllowance{ - SpendLimit: spendableCoins, - Expiration: &oneYear, - }, granterStr, granteeStr) - if err != nil { - return simtypes.NoOpMsg(feegrant.ModuleName, TypeMsgGrantAllowance, err.Error()), nil, err - } - - txCtx := simulation.OperationInput{ - R: r, - App: app, - TxGen: txConfig, - Cdc: nil, - Msg: msg, - Context: ctx, - SimAccount: granter, - AccountKeeper: ak, - Bankkeeper: bk, - ModuleName: feegrant.ModuleName, - CoinsSpentInMsg: spendableCoins, - } - - return simulation.GenAndDeliverTxWithRandFees(txCtx) - } -} - -// SimulateMsgRevokeAllowance generates a MsgRevokeAllowance with random values. -func SimulateMsgRevokeAllowance( - txConfig client.TxConfig, - ak feegrant.AccountKeeper, - bk feegrant.BankKeeper, - k keeper.Keeper, -) simtypes.Operation { - return func( - r *rand.Rand, app simtypes.AppEntrypoint, ctx sdk.Context, accs []simtypes.Account, chainID string, - ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { - hasGrant := false - - var granterAddr sdk.AccAddress - var granteeAddr sdk.AccAddress - err := k.IterateAllFeeAllowances(ctx, func(grant feegrant.Grant) bool { - granter, err := ak.AddressCodec().StringToBytes(grant.Granter) - if err != nil { - panic(err) - } - grantee, err := ak.AddressCodec().StringToBytes(grant.Grantee) - if err != nil { - panic(err) - } - granterAddr = granter - granteeAddr = grantee - hasGrant = true - return true - }) - if err != nil { - return simtypes.OperationMsg{}, nil, err - } - - if !hasGrant { - return simtypes.NoOpMsg(feegrant.ModuleName, TypeMsgRevokeAllowance, "no grants"), nil, nil - } - granter, ok := simtypes.FindAccount(accs, granterAddr) - - if !ok { - return simtypes.NoOpMsg(feegrant.ModuleName, TypeMsgRevokeAllowance, "Account not found"), nil, nil - } - - account := ak.GetAccount(ctx, granter.Address) - spendableCoins := bk.SpendableCoins(ctx, account.GetAddress()) - - granterStr, err := ak.AddressCodec().BytesToString(granterAddr) - if err != nil { - return simtypes.NoOpMsg(feegrant.ModuleName, TypeMsgRevokeAllowance, err.Error()), nil, err - } - granteeStr, err := ak.AddressCodec().BytesToString(granteeAddr) - if err != nil { - return simtypes.NoOpMsg(feegrant.ModuleName, TypeMsgRevokeAllowance, err.Error()), nil, err - } - msg := feegrant.NewMsgRevokeAllowance(granterStr, granteeStr) - - txCtx := simulation.OperationInput{ - R: r, - App: app, - TxGen: txConfig, - Cdc: nil, - Msg: &msg, - Context: ctx, - SimAccount: granter, - AccountKeeper: ak, - Bankkeeper: bk, - ModuleName: feegrant.ModuleName, - CoinsSpentInMsg: spendableCoins, - } - - return simulation.GenAndDeliverTxWithRandFees(txCtx) - } -} diff --git a/x/genutil/client/cli/gentx_test.go b/x/genutil/client/cli/gentx_test.go index 221ce645da43..f3cd97a01844 100644 --- a/x/genutil/client/cli/gentx_test.go +++ b/x/genutil/client/cli/gentx_test.go @@ -109,7 +109,6 @@ func (s *CLITestSuite) TestGenTxCmd() { } for _, tc := range tests { - tc := tc dir := s.T().TempDir() genTxFile := filepath.Join(dir, "myTx") diff --git a/x/genutil/client/cli/migrate.go b/x/genutil/client/cli/migrate.go index 2763ba06cfb4..2b2a1c856b74 100644 --- a/x/genutil/client/cli/migrate.go +++ b/x/genutil/client/cli/migrate.go @@ -29,7 +29,7 @@ func MigrateGenesisCmd(migrations types.MigrationMap) *cobra.Command { Use: "migrate ", Short: "Migrate genesis to a specified target version", Long: "Migrate the source genesis into the target version and print to STDOUT", - Example: fmt.Sprintf("%s migrate v0.47 /path/to/genesis.json --chain-id=cosmoshub-3 --genesis-time=2019-04-22T17:00:00Z", version.AppName), + Example: fmt.Sprintf("%s genesis migrate v0.47 /path/to/genesis.json --chain-id=cosmoshub-3 --genesis-time=2019-04-22T17:00:00Z", version.AppName), Args: cobra.ExactArgs(2), RunE: func(cmd *cobra.Command, args []string) error { return MigrateHandler(cmd, args, migrations) diff --git a/x/genutil/client/cli/migrate_test.go b/x/genutil/client/cli/migrate_test.go index 7e84b491b132..5cd7485d441c 100644 --- a/x/genutil/client/cli/migrate_test.go +++ b/x/genutil/client/cli/migrate_test.go @@ -50,7 +50,6 @@ func TestMigrateGenesis(t *testing.T) { } for _, tc := range testCases { - tc := tc t.Run(tc.name, func(t *testing.T) { genesisFile := testutil.WriteToNewTempFile(t, tc.genesis) jsonOutput, err := clitestutil.ExecTestCLICmd( diff --git a/x/genutil/client/cli/validate_genesis_test.go b/x/genutil/client/cli/validate_genesis_test.go index 2608f448d54b..41c337f13732 100644 --- a/x/genutil/client/cli/validate_genesis_test.go +++ b/x/genutil/client/cli/validate_genesis_test.go @@ -62,7 +62,7 @@ func TestValidateGenesis(t *testing.T) { }(), "section is missing in the app_state", module.NewManagerFromMap(map[string]appmodulev2.AppModule{ - "custommod": staking.NewAppModule(cdc, nil, nil, nil), + "custommod": staking.NewAppModule(cdc, nil), }), }, { @@ -85,8 +85,6 @@ func TestValidateGenesis(t *testing.T) { } for _, tc := range testCases { - tc := tc - t.Run(tc.name, func(t *testing.T) { genesisFile := testutil.WriteToNewTempFile(t, tc.genesis) _, err := clitestutil.ExecTestCLICmd(client.Context{}, cli.ValidateGenesisCmd(tc.genMM), []string{genesisFile.Name()}) diff --git a/x/genutil/gentx_test.go b/x/genutil/gentx_test.go index 10721c819e12..d93199ce2e6c 100644 --- a/x/genutil/gentx_test.go +++ b/x/genutil/gentx_test.go @@ -36,7 +36,7 @@ var ( pk2 = priv2.PubKey() addr1 = sdk.AccAddress(pk1.Address()) addr2 = sdk.AccAddress(pk2.Address()) - desc = stakingtypes.NewDescription("testname", "", "", "", "") + desc = stakingtypes.NewDescription("testname", "", "", "", "", stakingtypes.Metadata{}) comm = stakingtypes.CommissionRates{} ) diff --git a/x/genutil/types/genesis_state_test.go b/x/genutil/types/genesis_state_test.go index b5741bef7f81..9e04d9a5f571 100644 --- a/x/genutil/types/genesis_state_test.go +++ b/x/genutil/types/genesis_state_test.go @@ -39,7 +39,7 @@ func TestNetGenesisState(t *testing.T) { } func TestValidateGenesisMultipleMessages(t *testing.T) { - desc := stakingtypes.NewDescription("testname", "", "", "", "") + desc := stakingtypes.NewDescription("testname", "", "", "", "", stakingtypes.Metadata{}) comm := stakingtypes.CommissionRates{} valAc := codectestutil.CodecOptions{}.GetValidatorCodec() @@ -66,7 +66,7 @@ func TestValidateGenesisMultipleMessages(t *testing.T) { } func TestValidateGenesisBadMessage(t *testing.T) { - desc := stakingtypes.NewDescription("testname", "", "", "", "") + desc := stakingtypes.NewDescription("testname", "", "", "", "", stakingtypes.Metadata{}) pk1Addr, err := codectestutil.CodecOptions{}.GetValidatorCodec().BytesToString(pk1.Address()) require.NoError(t, err) msg1 := stakingtypes.NewMsgEditValidator(pk1Addr, desc, nil, nil) diff --git a/x/genutil/utils_test.go b/x/genutil/utils_test.go index af2963df41fd..8304c290e647 100644 --- a/x/genutil/utils_test.go +++ b/x/genutil/utils_test.go @@ -51,7 +51,6 @@ func TestInitializeNodeValidatorFilesFromMnemonic(t *testing.T) { } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { _, _, err := InitializeNodeValidatorFilesFromMnemonic(cfg, tt.mnemonic, "ed25519") diff --git a/x/gov/README.md b/x/gov/README.md index 15f86d335b1e..cda1af118b6c 100644 --- a/x/gov/README.md +++ b/x/gov/README.md @@ -18,13 +18,9 @@ currently supports: * **Proposal submission:** Users can submit proposals with a deposit. Once the minimum deposit is reached, the proposal enters voting period. The minimum deposit can be reached by collecting deposits from different users (including proposer) within deposit period. * **Vote:** Participants can vote on proposals that reached MinDeposit and entered voting period. -* **Inheritance and penalties:** Delegators inherit their validator's vote if -they don't vote themselves. +* **Inheritance and penalties:** Delegators, by default, inherit their validator's vote if they don't vote themselves. * **Claiming deposit:** Users that deposited on proposals can recover their -deposits if the proposal was accepted or rejected. If the proposal was vetoed, or never entered voting period (minimum deposit not reached within deposit period), the deposit is burned. - -This module is in use on the Cosmos Hub (a.k.a [gaia](https://github.com/cosmos/gaia)). - +deposits if the proposal was accepted or rejected. If the proposal was vetoed, or never entered voting period (minimum deposit not reached within deposit period), the deposit is burned (or refunded depending on the gov parameters). ## Contents @@ -59,7 +55,6 @@ staking token of the chain. * [Metadata](#metadata) * [Proposal](#proposal-3) * [Vote](#vote-5) -* [Future Improvements](#future-improvements) ## Concepts @@ -87,7 +82,7 @@ proposal passes. The messages are executed by the governance `ModuleAccount` its such as `x/upgrade`, that want to allow certain messages to be executed by governance only should add a whitelist within the respective msg server, granting the governance module the right to execute the message once a quorum has been reached. The governance -module uses the `MsgServiceRouter` to check that these messages are correctly constructed +module uses the core `router.Service` to check that these messages are correctly constructed and have a respective path to execute on but do not perform a full validity check. :::warning @@ -118,16 +113,22 @@ proposal is finalized (passed or rejected). #### Deposit refund and burn When a proposal is finalized, the coins from the deposit are either refunded or burned -according to the final tally of the proposal: +according to the final tally of the proposal and the governance module parameters: +* All refunded or burned deposits are removed from the state. Events are issued when + burning or refunding a deposit. * If the proposal is approved or rejected but *not* vetoed, each deposit will be automatically refunded to its respective depositor (transferred from the governance `ModuleAccount`). -* When the proposal is vetoed with greater than 1/3, deposits will be burned from the - governance `ModuleAccount` and the proposal information along with its deposit - information will be removed from state. -* All refunded or burned deposits are removed from the state. Events are issued when - burning or refunding a deposit. +* If the proposal is marked as Spam, the deposit will be burned. + +For other cases, they are three parameters that define if the deposit of a proposal should be burned or returned to the depositors. + +* `BurnVoteVeto` burns the proposal deposit if the proposal gets vetoed. +* `BurnVoteQuorum` burns the proposal deposit if the vote does not reach quorum. +* `BurnProposalDepositPrevote` burns the proposal deposit if it does not enter the voting phase. + +> Note: These parameters are modifiable via governance. ### Vote @@ -144,7 +145,7 @@ Note that when *participants* have bonded and unbonded Atoms, their voting power Once a proposal reaches `MinDeposit`, it immediately enters `Voting period`. We define `Voting period` as the interval between the moment the vote opens and -the moment the vote closes. The initial value of `Voting period` is 2 weeks. +the moment the vote closes. The default value of `Voting period` is 2 weeks but is modifiable at genesis or governance. #### Option set @@ -163,8 +164,6 @@ The initial option set includes the following options: allows voters to signal that they do not intend to vote in favor or against the proposal but accept the result of the vote. -*Note: from the UI, for urgent proposals we should maybe add a ‘Not Urgent’ option that casts a `NoWithVeto` vote.* - #### Weighted Votes [ADR-037](https://github.com/cosmos/cosmos-sdk/blob/main/docs/architecture/adr-037-gov-split-vote.md) introduces the weighted vote feature which allows a staker to split their votes into several voting options. For example, it could use 70% of its voting power to vote Yes and 30% of its voting power to vote No. @@ -174,11 +173,11 @@ Often times the entity owning that address might not be a single individual. For To represent weighted vote on chain, we use the following Protobuf message. ```protobuf reference -https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/gov/v1beta1/gov.proto#L34-L47 +https://github.com/cosmos/cosmos-sdk/blob/v0.52.0-beta.1/x/gov/proto/cosmos/gov/v1/gov.proto#L56-L63 ``` ```protobuf reference -https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/gov/v1beta1/gov.proto#L181-L201 +https://github.com/cosmos/cosmos-sdk/blob/v0.52.0-beta.1/x/gov/proto/cosmos/gov/v1/gov.proto#L202-L219 ``` For a weighted vote to be valid, the `options` field must not contain duplicate vote options, and the sum of weights of all options must be equal to 1. @@ -204,7 +203,7 @@ By default, `YesQuorum` is set to 0, which means no minimum. ### Proposal Types -Proposal types have been introduced in ADR-069. +Proposal types have been introduced in [ADR-069](https://github.com/cosmos/cosmos-sdk/blob/main/docs/architecture/adr-069-gov-improvements.md). #### Standard proposal @@ -225,17 +224,16 @@ A chain can optionally set a list of authorized addresses that can submit optimi #### Multiple Choice Proposals A multiple choice proposal is a proposal where the voting options can be defined by the proposer. -The number of voting options is limited to a maximum of 4. +The number of voting options is limited to a maximum of **4**. Multiple choice proposals, contrary to any other proposal type, cannot have messages to execute. They are only text proposals. -#### Threshold +### Threshold -Threshold is defined as the minimum proportion of `Yes` votes (excluding -`Abstain` votes) for the proposal to be accepted. +Threshold is defined as the minimum proportion of `Yes` votes (excluding `Abstain` votes) for the proposal to be accepted. -Initially, the threshold is set at 50% of `Yes` votes, excluding `Abstain` -votes. A possibility to veto exists if more than 1/3rd of all votes are -`NoWithVeto` votes. Note, both of these values are derived from the `TallyParams` +Initially, the threshold is set at 50% of `Yes` votes, excluding `Abstain` votes. +A possibility to veto exists if more than 1/3rd of all votes are `NoWithVeto` votes. +Note, both of these values are derived from the `Params` on-chain parameter, which is modifiable by governance. This means that proposals are accepted iff: @@ -249,43 +247,37 @@ This means that proposals are accepted iff: For expedited proposals, by default, the threshold is higher than with a *normal proposal*, namely, 66.7%. -#### Inheritance +### Inheritance -If a delegator does not vote, it will inherit its validator vote. +If a delegator does not vote, by default, it will inherit its validator vote. -* If the delegator votes before its validator, it will not inherit from the - validator's vote. -* If the delegator votes after its validator, it will override its validator - vote with its own. If the proposal is urgent, it is possible - that the vote will close before delegators have a chance to react and +* If the delegator votes before its validator, it will not inherit from the validator's vote. +* If the delegator votes after its validator, it will override its validator vote with its own. + If the proposal is urgent, it is possible that the vote will close before delegators have a chance to react and override their validator's vote. This is not a problem, as proposals require more than 2/3rd of the total voting power to pass, when tallied at the end of the voting period. Because as little as 1/3 + 1 validation power could collude to censor transactions, non-collusion is already assumed for ranges exceeding this threshold. -#### Validator’s punishment for non-voting - -At present, validators are not punished for failing to vote. - -#### Governance address - -Later, we may add permissioned keys that could only sign txs from certain modules. For the MVP, the `Governance address` will be the main validator address generated at account creation. This address corresponds to a different PrivKey than the CometBFT PrivKey which is responsible for signing consensus messages. Validators thus do not have to sign governance transactions with the sensitive CometBFT PrivKey. - -#### Burnable Params +This behavior can be changed by passing a custom tally calculation function to the governance module. -There are three parameters that define if the deposit of a proposal should be burned or returned to the depositors. +```go reference +https://github.com/cosmos/cosmos-sdk/blob/v0.52.0-beta.1/x/gov/keeper/config.go#L33-L35 +``` -* `BurnVoteVeto` burns the proposal deposit if the proposal gets vetoed. -* `BurnVoteQuorum` burns the proposal deposit if the vote does not reach quorum. -* `BurnProposalDepositPrevote` burns the proposal deposit if it does not enter the voting phase. +#### Validator’s punishment for non-voting -> Note: These parameters are modifiable via governance. +At present, validators are not punished for failing to vote. #### Execution -Execution is the process of executing the messages contained in a proposal. The execution phase will commence after the proposal has been accepted by the network. The messages contained in the proposal will be executed in the order they were submitted. +Execution is the process of executing the messages contained in a proposal. The execution phase will commence after the proposal has been accepted by the network. The messages contained in the proposal will be executed in the order they were submitted. All messages must be executed successfully for the proposal to be considered successful. I + +If a proposal passes but fails to execute, the proposal will be marked as `StatusFailed`. This status is different from `StatusRejected`, which is used when a proposal fails to pass. Execution has an upper limit on how much gas can be consumed in a single block. This limit is defined by the `ProposalExecutionGas` parameter. ## State +The governance module uses [collections](https://docs.cosmos.network/v0.50/build/packages/collections) for state management. + ### Constitution `Constitution` is found in the genesis state. It is a string field intended to be used to describe the purpose of a particular blockchain, and its expected norms. A few examples of how the constitution field can be used: @@ -328,7 +320,7 @@ unique id and contains a series of timestamps: `submit_time`, `deposit_end_time` `voting_start_time`, `voting_end_time` which track the lifecycle of a proposal ```protobuf reference -https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/gov/v1/gov.proto#L51-L99 +https://github.com/cosmos/cosmos-sdk/blob/v0.52.0-beta.1/x/gov/proto/cosmos/gov/v1/gov.proto#L78-L134 ``` A proposal will generally require more than just a set of messages to explain its @@ -354,7 +346,13 @@ the following `JSON` template: This makes it far easier for clients to support multiple networks. Fields metadata, title and summary have a maximum length that is chosen by the app developer, and -passed into the gov keeper as a config. The default maximum length are: for the title 255 characters, for the metadata 255 characters and for summary 10200 characters (40 times the one of the title). +passed into the gov keeper as a config (`x/gov/keeper/config`). + +The default maximum length are: + +```go reference +https://github.com/cosmos/cosmos-sdk/blob/v0.52.0-beta.1/x/gov/keeper/config.go#L38-L47 +``` #### Writing a module that uses governance @@ -372,37 +370,20 @@ Note, any message can be executed by governance if embedded in `MsgSudoExec`. ### Parameters and base types -`Parameters` define the rules according to which votes are run. There can only -be one active parameter set at any given time. If governance wants to change a -parameter set, either to modify a value or add/remove a parameter field, a new -parameter set has to be created and the previous one rendered inactive. - -#### DepositParams - -```protobuf reference -https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/gov/v1/gov.proto#L152-L162 -``` - -#### VotingParams - -```protobuf reference -https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/gov/v1/gov.proto#L164-L168 -``` - -#### TallyParams +`Params` define the rules according to which votes are run. If governance wants to change a +parameter it can do so by submitting a gov `MsgUpdateParams` governance proposal. ```protobuf reference -https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/gov/v1/gov.proto#L170-L182 +https://github.com/cosmos/cosmos-sdk/blob/v0.52.0-beta.1/x/gov/proto/cosmos/gov/v1/gov.proto#L259-L348 ``` -Parameters are stored in a global `GlobalParams` KVStore. +Parameters are stored in the `gov` store under the key `ParamsKey`. Additionally, we introduce some basic types: ```go type ProposalStatus byte - const ( StatusNil ProposalStatus = 0x00 StatusDepositPeriod ProposalStatus = 0x01 // Proposal is submitted. Participants can deposit on it but not vote @@ -416,7 +397,7 @@ const ( ### Deposit ```protobuf reference -https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/gov/v1/gov.proto#L38-L49 +https://github.com/cosmos/cosmos-sdk/blob/v0.52.0-beta.1/x/gov/proto/cosmos/gov/v1/gov.proto#L65-L76 ``` ### ValidatorGovInfo @@ -430,50 +411,12 @@ This type is used in a temp map when tallying } ``` -## Stores - -:::note -Stores are KVStores in the multi-store. The key to find the store is the first parameter in the list -::: - -We will use one KVStore `Governance` to store four mappings: - -* A mapping from `proposalID|'proposal'` to `Proposal`. -* A mapping from `proposalID|'addresses'|address` to `Vote`. This mapping allows - us to query all addresses that voted on the proposal along with their vote by - doing a range query on `proposalID:addresses`. -* A mapping from `ParamsKey|'Params'` to `Params`. This map allows to query all - x/gov params. - -For pseudocode purposes, here are the two functions we will use to read or write in stores: - -* `load(StoreKey, Key)`: Retrieve item stored at key `Key` in store found at key `StoreKey` in the multistore -* `store(StoreKey, Key, value)`: Write value `Value` at key `Key` in store found at key `StoreKey` in the multistore - -### Proposal Processing Queue - -**Store:** - -* `ProposalProcessingQueue`: A queue `queue[proposalID]` containing all the - `ProposalIDs` of proposals that reached `MinDeposit`. During each `EndBlock`, - all the proposals that have reached the end of their voting period are processed. - To process a finished proposal, the application tallies the votes, computes the - votes of each validator and checks if every validator in the validator set has - voted. If the proposal is accepted, deposits are refunded. Finally, the proposal - content `Handler` is executed. - ### Legacy Proposal :::warning -Legacy proposals are deprecated. Use the new proposal flow by granting the governance module the right to execute the message. +Legacy proposals (`gov/v1beta1`) are deprecated. Use the new proposal flow by granting the governance module the right to execute the message. ::: -A legacy proposal is the old implementation of governance proposal. -Contrary to proposal that can contain any messages, a legacy proposal allows to submit a set of pre-defined proposals. -These proposals are defined by their types and handled by handlers that are registered in the gov v1beta1 router. - -More information on how to submit proposals is in the [client section](#client). - ## Messages ### Proposal Submission @@ -481,37 +424,28 @@ More information on how to submit proposals is in the [client section](#client). Proposals can be submitted by any account via a `MsgSubmitProposal` or a `MsgSubmitMultipleChoiceProposal` transaction. ```protobuf reference -https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/gov/v1/tx.proto#L42-L69 +https://github.com/cosmos/cosmos-sdk/blob/v0.52.0-beta.1/x/gov/proto/cosmos/gov/v1/tx.proto#L64-L102 ``` -:::note +```protobuf reference +https://github.com/cosmos/cosmos-sdk/blob/v0.52.0-beta.1/x/gov/proto/cosmos/gov/v1/tx.proto#L229-L256 +``` + +:::tip A multiple choice proposal is a proposal where the voting options can be defined by the proposer. It cannot have messages to execute. It is only a text proposal. -::: - -:::warning -Submitting a multiple choice proposal using `MsgSubmitProposal` is invalid, as vote options cannot be defined. +This means submitting a multiple choice proposal using `MsgSubmitProposal` is invalid, as vote options cannot be defined. ::: All `sdk.Msgs` passed into the `messages` field of a `MsgSubmitProposal` message -must be registered in the app's `MsgServiceRouter`. Each of these messages must +must be registered in the app's message router. Each of these messages must have one signer, namely the gov module account. And finally, the metadata length must not be larger than the `maxMetadataLen` config passed into the gov keeper. The `initialDeposit` must be strictly positive and conform to the accepted denom of the `MinDeposit` param. -**State modifications:** - -* Generate new `proposalID` -* Create new `Proposal` -* Initialise `Proposal`'s attributes -* Decrease balance of sender by `InitialDeposit` -* If `MinDeposit` is reached: - * Push `proposalID` in `ProposalProcessingQueue` -* Transfer `InitialDeposit` from the `Proposer` to the governance `ModuleAccount` - ### Deposit -Once a proposal is submitted, if `Proposal.TotalDeposit < ActiveParam.MinDeposit`, Atom holders can send +Once a proposal is submitted, if `Proposal.TotalDeposit < GovParams.MinDeposit`, Atom holders can send `MsgDeposit` transactions to increase the proposal's deposit. A deposit is accepted iff: @@ -521,36 +455,19 @@ A deposit is accepted iff: * The deposited coins are conform to the accepted denom from the `MinDeposit` param ```protobuf reference -https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/gov/v1/tx.proto#L134-L147 +https://github.com/cosmos/cosmos-sdk/blob/v0.52.0-beta.1/x/gov/proto/cosmos/gov/v1/tx.proto#L167-L180 ``` -**State modifications:** - -* Decrease balance of sender by `deposit` -* Add `deposit` of sender in `proposal.Deposits` -* Increase `proposal.TotalDeposit` by sender's `deposit` -* If `MinDeposit` is reached: - * Push `proposalID` in `ProposalProcessingQueueEnd` -* Transfer `Deposit` from the `proposer` to the governance `ModuleAccount` - ### Vote -Once `ActiveParam.MinDeposit` is reached, voting period starts. From there, +Once `GovParams.MinDeposit` is reached, voting period starts. From there, bonded Atom holders are able to send `MsgVote` transactions to cast their vote on the proposal. ```protobuf reference -https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/gov/v1/tx.proto#L92-L108 +https://github.com/cosmos/cosmos-sdk/blob/v0.52.0-beta.1/x/gov/proto/cosmos/gov/v1/tx.proto#L125-L141 ``` -**State modifications:** - -* Record `Vote` of sender - -:::note -Gas cost for this message has to take into account the future tallying of the vote in EndBlocker. -::: - ## Events The governance module emits the following events: @@ -659,9 +576,44 @@ In addition to the parameters above, the governance module can also be configure If configured, these params will take precedence over the global params for a specific proposal. :::warning -Currently, messaged based parameters limit the number of messages that can be included in a proposal to 1 if a messaged based parameter is configured. +Currently, messaged based parameters limit the number of messages that can be included in a proposal. +Only messages that have the same message parameters can be included in the same proposal. +::: + +## Metadata + +The gov module has two locations for metadata where users can provide further context about the on-chain actions they are taking. By default all metadata fields have a 255 character length field where metadata can be stored in json format, either on-chain or off-chain depending on the amount of data required. Here we provide a recommendation for the json structure and where the data should be stored. There are two important factors in making these recommendations. First, that the gov and group modules are consistent with one another, note the number of proposals made by all groups may be quite large. Second, that client applications such as block explorers and governance interfaces have confidence in the consistency of metadata structure across chains. + +### Proposal + +Location: off-chain as json object stored on IPFS (mirrors [group proposal](../group/README.md#metadata)) + +```json +{ + "title": "", + "authors": [""], + "summary": "", + "details": "", + "proposal_forum_url": "", + "vote_option_context": "", +} +``` + +:::note +The `authors` field is an array of strings, this is to allow for multiple authors to be listed in the metadata. +In v0.46, the `authors` field is a comma-separated string. Frontends are encouraged to support both formats for backwards compatibility. ::: +### Vote + +Location: on-chain as json within 255 character limit (mirrors [group vote](../group/README.md#metadata)) + +```json +{ + "justification": "", +} +``` + ## Client ### CLI @@ -1043,41 +995,6 @@ By default the metadata, summary and title are both limited by 255 characters, t When metadata is not specified, the title is limited to 255 characters and the summary 40x the title length. ::: -##### submit-legacy-proposal - -The `submit-legacy-proposal` command allows users to submit a governance legacy proposal along with an initial deposit. - -```bash -simd tx gov submit-legacy-proposal [command] [flags] -``` - -Example: - -```bash -simd tx gov submit-legacy-proposal --title="Test Proposal" --description="testing" --type="Text" --deposit="100000000stake" --from cosmos1.. -``` - -Example (`param-change`): - -```bash -simd tx gov submit-legacy-proposal param-change proposal.json --from cosmos1.. -``` - -```json -{ - "title": "Test Proposal", - "description": "testing, testing, 1, 2, 3", - "changes": [ - { - "subspace": "staking", - "key": "MaxValidators", - "value": 100 - } - ], - "deposit": "10000000stake" -} -``` - ##### cancel-proposal Once proposal is canceled, from the deposits of proposal `deposits * proposal_cancel_ratio` will be burned or sent to `ProposalCancelDest` address , if `ProposalCancelDest` is empty then deposits will be burned. The `remaining deposits` will be sent to depositors. @@ -1128,10 +1045,8 @@ A user can query the `gov` module using gRPC endpoints. The `Proposal` endpoint allows users to query a given proposal. -Using legacy v1beta1: - ```bash -cosmos.gov.v1beta1.Query/Proposal +cosmos.gov.v1.Query/Proposal ``` Example: @@ -1140,312 +1055,99 @@ Example: grpcurl -plaintext \ -d '{"proposal_id":"1"}' \ localhost:9090 \ - cosmos.gov.v1beta1.Query/Proposal + cosmos.gov.v1.Query/Proposal ``` -Example Output: - -```bash -{ - "proposal": { - "proposalId": "1", - "content": {"@type":"/cosmos.gov.v1beta1.TextProposal","description":"testing, testing, 1, 2, 3","title":"Test Proposal"}, - "status": "PROPOSAL_STATUS_VOTING_PERIOD", - "finalTallyResult": { - "yes": "0", - "abstain": "0", - "no": "0", - "noWithVeto": "0" - }, - "submitTime": "2021-09-16T19:40:08.712440474Z", - "depositEndTime": "2021-09-18T19:40:08.712440474Z", - "totalDeposit": [ - { - "denom": "stake", - "amount": "10000000" - } - ], - "votingStartTime": "2021-09-16T19:40:08.712440474Z", - "votingEndTime": "2021-09-18T19:40:08.712440474Z", - "title": "Test Proposal", - "summary": "testing, testing, 1, 2, 3" - } -} -``` +#### Proposals -Using v1: +The `Proposals` endpoint allows users to query all proposals with optional filters. ```bash -cosmos.gov.v1.Query/Proposal +cosmos.gov.v1.Query/Proposals ``` Example: ```bash grpcurl -plaintext \ - -d '{"proposal_id":"1"}' \ localhost:9090 \ - cosmos.gov.v1.Query/Proposal -``` - -Example Output: - -```bash -{ - "proposal": { - "id": "1", - "messages": [ - {"@type":"/cosmos.bank.v1beta1.MsgSend","amount":[{"denom":"stake","amount":"10"}],"fromAddress":"cosmos1..","toAddress":"cosmos1.."} - ], - "status": "PROPOSAL_STATUS_VOTING_PERIOD", - "finalTallyResult": { - "yesCount": "0", - "abstainCount": "0", - "noCount": "0", - "noWithVetoCount": "0" - }, - "submitTime": "2022-03-28T11:50:20.819676256Z", - "depositEndTime": "2022-03-30T11:50:20.819676256Z", - "totalDeposit": [ - { - "denom": "stake", - "amount": "10000000" - } - ], - "votingStartTime": "2022-03-28T14:25:26.644857113Z", - "votingEndTime": "2022-03-30T14:25:26.644857113Z", - "metadata": "AQ==", - "title": "Test Proposal", - "summary": "testing, testing, 1, 2, 3" - } -} + cosmos.gov.v1.Query/Proposals ``` -#### Proposals - -The `Proposals` endpoint allows users to query all proposals with optional filters. +#### Vote -Using legacy v1beta1: +The `Vote` endpoint allows users to query a vote for a given proposal. ```bash -cosmos.gov.v1beta1.Query/Proposals +cosmos.gov.v1.Query/Vote ``` Example: ```bash grpcurl -plaintext \ + -d '{"proposal_id":"1","voter":"cosmos1.."}' \ localhost:9090 \ - cosmos.gov.v1beta1.Query/Proposals + cosmos.gov.v1.Query/Vote ``` -Example Output: - -```bash -{ - "proposals": [ - { - "proposalId": "1", - "status": "PROPOSAL_STATUS_VOTING_PERIOD", - "finalTallyResult": { - "yes": "0", - "abstain": "0", - "no": "0", - "noWithVeto": "0" - }, - "submitTime": "2022-03-28T11:50:20.819676256Z", - "depositEndTime": "2022-03-30T11:50:20.819676256Z", - "totalDeposit": [ - { - "denom": "stake", - "amount": "10000000010" - } - ], - "votingStartTime": "2022-03-28T14:25:26.644857113Z", - "votingEndTime": "2022-03-30T14:25:26.644857113Z" - }, - { - "proposalId": "2", - "status": "PROPOSAL_STATUS_DEPOSIT_PERIOD", - "finalTallyResult": { - "yes": "0", - "abstain": "0", - "no": "0", - "noWithVeto": "0" - }, - "submitTime": "2022-03-28T14:02:41.165025015Z", - "depositEndTime": "2022-03-30T14:02:41.165025015Z", - "totalDeposit": [ - { - "denom": "stake", - "amount": "10" - } - ], - "votingStartTime": "0001-01-01T00:00:00Z", - "votingEndTime": "0001-01-01T00:00:00Z" - } - ], - "pagination": { - "total": "2" - } -} - -``` +#### Votes -Using v1: +The `Votes` endpoint allows users to query all votes for a given proposal. ```bash -cosmos.gov.v1.Query/Proposals +cosmos.gov.v1.Query/Votes ``` Example: ```bash grpcurl -plaintext \ + -d '{"proposal_id":"1"}' \ localhost:9090 \ - cosmos.gov.v1.Query/Proposals -``` - -Example Output: - -```bash -{ - "proposals": [ - { - "id": "1", - "messages": [ - {"@type":"/cosmos.bank.v1beta1.MsgSend","amount":[{"denom":"stake","amount":"10"}],"fromAddress":"cosmos1..","toAddress":"cosmos1.."} - ], - "status": "PROPOSAL_STATUS_VOTING_PERIOD", - "finalTallyResult": { - "yesCount": "0", - "abstainCount": "0", - "noCount": "0", - "noWithVetoCount": "0" - }, - "submitTime": "2022-03-28T11:50:20.819676256Z", - "depositEndTime": "2022-03-30T11:50:20.819676256Z", - "totalDeposit": [ - { - "denom": "stake", - "amount": "10000000010" - } - ], - "votingStartTime": "2022-03-28T14:25:26.644857113Z", - "votingEndTime": "2022-03-30T14:25:26.644857113Z", - "metadata": "AQ==", - "title": "Proposal Title", - "summary": "Proposal Summary" - }, - { - "id": "2", - "messages": [ - {"@type":"/cosmos.bank.v1beta1.MsgSend","amount":[{"denom":"stake","amount":"10"}],"fromAddress":"cosmos1..","toAddress":"cosmos1.."} - ], - "status": "PROPOSAL_STATUS_DEPOSIT_PERIOD", - "finalTallyResult": { - "yesCount": "0", - "abstainCount": "0", - "noCount": "0", - "noWithVetoCount": "0" - }, - "submitTime": "2022-03-28T14:02:41.165025015Z", - "depositEndTime": "2022-03-30T14:02:41.165025015Z", - "totalDeposit": [ - { - "denom": "stake", - "amount": "10" - } - ], - "metadata": "AQ==", - "title": "Proposal Title", - "summary": "Proposal Summary" - } - ], - "pagination": { - "total": "2" - } -} + cosmos.gov.v1.Query/Votes ``` -#### Vote - -The `Vote` endpoint allows users to query a vote for a given proposal. +#### Params -Using legacy v1beta1: +The `Params` endpoint allows users to query all parameters for the `gov` module. ```bash -cosmos.gov.v1beta1.Query/Vote +cosmos.gov.v1.Query/Params ``` Example: ```bash grpcurl -plaintext \ - -d '{"proposal_id":"1","voter":"cosmos1.."}' \ + -d '{"params_type":"voting"}' \ localhost:9090 \ - cosmos.gov.v1beta1.Query/Vote + cosmos.gov.v1.Query/Params ``` -Example Output: - -```bash -{ - "vote": { - "proposalId": "1", - "voter": "cosmos1..", - "option": "VOTE_OPTION_YES", - "options": [ - { - "option": "VOTE_OPTION_YES", - "weight": "1000000000000000000" - } - ] - } -} -``` +#### Deposit -Using v1: +The `Deposit` endpoint allows users to query a deposit for a given proposal from a given depositor. ```bash -cosmos.gov.v1.Query/Vote +cosmos.gov.v1.Query/Deposit ``` Example: ```bash grpcurl -plaintext \ - -d '{"proposal_id":"1","voter":"cosmos1.."}' \ + '{"proposal_id":"1","depositor":"cosmos1.."}' \ localhost:9090 \ - cosmos.gov.v1.Query/Vote -``` - -Example Output: - -```bash -{ - "vote": { - "proposalId": "1", - "voter": "cosmos1..", - "option": "VOTE_OPTION_YES", - "options": [ - { - "option": "VOTE_OPTION_YES", - "weight": "1.000000000000000000" - } - ] - } -} + cosmos.gov.v1.Query/Deposit ``` -#### Votes - -The `Votes` endpoint allows users to query all votes for a given proposal. +#### deposits -Using legacy v1beta1: +The `Deposits` endpoint allows users to query all deposits for a given proposal. ```bash -cosmos.gov.v1beta1.Query/Votes +cosmos.gov.v1.Query/Deposits ``` Example: @@ -1454,35 +1156,15 @@ Example: grpcurl -plaintext \ -d '{"proposal_id":"1"}' \ localhost:9090 \ - cosmos.gov.v1beta1.Query/Votes + cosmos.gov.v1.Query/Deposits ``` -Example Output: - -```bash -{ - "votes": [ - { - "proposalId": "1", - "voter": "cosmos1..", - "options": [ - { - "option": "VOTE_OPTION_YES", - "weight": "1000000000000000000" - } - ] - } - ], - "pagination": { - "total": "1" - } -} -``` +#### TallyResult -Using v1: +The `TallyResult` endpoint allows users to query the tally of a given proposal. ```bash -cosmos.gov.v1.Query/Votes +cosmos.gov.v1.Query/TallyResult ``` Example: @@ -1491,353 +1173,16 @@ Example: grpcurl -plaintext \ -d '{"proposal_id":"1"}' \ localhost:9090 \ - cosmos.gov.v1.Query/Votes + cosmos.gov.v1.Query/TallyResult ``` -Example Output: - -```bash -{ - "votes": [ - { - "proposalId": "1", - "voter": "cosmos1..", - "options": [ - { - "option": "VOTE_OPTION_YES", - "weight": "1.000000000000000000" - } - ] - } - ], - "pagination": { - "total": "1" - } -} -``` - -#### Params - -The `Params` endpoint allows users to query all parameters for the `gov` module. - -Using legacy v1beta1: - -```bash -cosmos.gov.v1beta1.Query/Params -``` - -Example: - -```bash -grpcurl -plaintext \ - -d '{"params_type":"voting"}' \ - localhost:9090 \ - cosmos.gov.v1beta1.Query/Params -``` - -Example Output: - -```bash -{ - "votingParams": { - "votingPeriod": "172800s" - }, - "depositParams": { - "maxDepositPeriod": "0s" - }, - "tallyParams": { - "quorum": "MA==", - "threshold": "MA==", - "vetoThreshold": "MA==" - } -} -``` - -Using v1: - -```bash -cosmos.gov.v1.Query/Params -``` - -Example: - -```bash -grpcurl -plaintext \ - -d '{"params_type":"voting"}' \ - localhost:9090 \ - cosmos.gov.v1.Query/Params -``` - -Example Output: - -```bash -{ - "votingParams": { - "votingPeriod": "172800s" - } -} -``` - -#### Deposit - -The `Deposit` endpoint allows users to query a deposit for a given proposal from a given depositor. - -Using legacy v1beta1: - -```bash -cosmos.gov.v1beta1.Query/Deposit -``` - -Example: - -```bash -grpcurl -plaintext \ - '{"proposal_id":"1","depositor":"cosmos1.."}' \ - localhost:9090 \ - cosmos.gov.v1beta1.Query/Deposit -``` - -Example Output: - -```bash -{ - "deposit": { - "proposalId": "1", - "depositor": "cosmos1..", - "amount": [ - { - "denom": "stake", - "amount": "10000000" - } - ] - } -} -``` - -Using v1: - -```bash -cosmos.gov.v1.Query/Deposit -``` - -Example: - -```bash -grpcurl -plaintext \ - '{"proposal_id":"1","depositor":"cosmos1.."}' \ - localhost:9090 \ - cosmos.gov.v1.Query/Deposit -``` - -Example Output: - -```bash -{ - "deposit": { - "proposalId": "1", - "depositor": "cosmos1..", - "amount": [ - { - "denom": "stake", - "amount": "10000000" - } - ] - } -} -``` - -#### deposits - -The `Deposits` endpoint allows users to query all deposits for a given proposal. - -Using legacy v1beta1: - -```bash -cosmos.gov.v1beta1.Query/Deposits -``` - -Example: - -```bash -grpcurl -plaintext \ - -d '{"proposal_id":"1"}' \ - localhost:9090 \ - cosmos.gov.v1beta1.Query/Deposits -``` - -Example Output: - -```bash -{ - "deposits": [ - { - "proposalId": "1", - "depositor": "cosmos1..", - "amount": [ - { - "denom": "stake", - "amount": "10000000" - } - ] - } - ], - "pagination": { - "total": "1" - } -} -``` - -Using v1: - -```bash -cosmos.gov.v1.Query/Deposits -``` - -Example: - -```bash -grpcurl -plaintext \ - -d '{"proposal_id":"1"}' \ - localhost:9090 \ - cosmos.gov.v1.Query/Deposits -``` - -Example Output: - -```bash -{ - "deposits": [ - { - "proposalId": "1", - "depositor": "cosmos1..", - "amount": [ - { - "denom": "stake", - "amount": "10000000" - } - ] - } - ], - "pagination": { - "total": "1" - } -} -``` - -#### TallyResult - -The `TallyResult` endpoint allows users to query the tally of a given proposal. - -Using legacy v1beta1: - -```bash -cosmos.gov.v1beta1.Query/TallyResult -``` - -Example: - -```bash -grpcurl -plaintext \ - -d '{"proposal_id":"1"}' \ - localhost:9090 \ - cosmos.gov.v1beta1.Query/TallyResult -``` - -Example Output: - -```bash -{ - "tally": { - "yes": "1000000", - "abstain": "0", - "no": "0", - "noWithVeto": "0", - "option_one_count": "1000000", - "option_two_count": "0", - "option_three_count": "0", - "option_four_count": "0", - "spam_count": "0" - } -} -``` - -Using v1: - -```bash -cosmos.gov.v1.Query/TallyResult -``` - -Example: - -```bash -grpcurl -plaintext \ - -d '{"proposal_id":"1"}' \ - localhost:9090 \ - cosmos.gov.v1.Query/TallyResult -``` - -Example Output: - -```bash -{ - "tally": { - "yes": "1000000", - "abstain": "0", - "no": "0", - "noWithVeto": "0" - } -} -``` - -### REST - -A user can query the `gov` module using REST endpoints. - -#### proposal - -The `proposals` endpoint allows users to query a given proposal. - -Using legacy v1beta1: - -```bash -/cosmos/gov/v1beta1/proposals/{proposal_id} -``` - -Example: - -```bash -curl localhost:1317/cosmos/gov/v1beta1/proposals/1 -``` - -Example Output: - -```bash -{ - "proposal": { - "proposal_id": "1", - "content": null, - "status": "PROPOSAL_STATUS_VOTING_PERIOD", - "final_tally_result": { - "yes": "0", - "abstain": "0", - "no": "0", - "no_with_veto": "0" - }, - "submit_time": "2022-03-28T11:50:20.819676256Z", - "deposit_end_time": "2022-03-30T11:50:20.819676256Z", - "total_deposit": [ - { - "denom": "stake", - "amount": "10000000010" - } - ], - "voting_start_time": "2022-03-28T14:25:26.644857113Z", - "voting_end_time": "2022-03-30T14:25:26.644857113Z" - } -} -``` - -Using v1: +### REST + +A user can query the `gov` module using REST endpoints. + +#### proposal + +The `proposals` endpoint allows users to query a given proposal. ```bash /cosmos/gov/v1/proposals/{proposal_id} @@ -1849,121 +1194,10 @@ Example: curl localhost:1317/cosmos/gov/v1/proposals/1 ``` -Example Output: - -```bash -{ - "proposal": { - "id": "1", - "messages": [ - { - "@type": "/cosmos.bank.v1beta1.MsgSend", - "from_address": "cosmos1..", - "to_address": "cosmos1..", - "amount": [ - { - "denom": "stake", - "amount": "10" - } - ] - } - ], - "status": "PROPOSAL_STATUS_VOTING_PERIOD", - "final_tally_result": { - "yes_count": "0", - "abstain_count": "0", - "no_count": "0", - "no_with_veto_count": "0" - }, - "submit_time": "2022-03-28T11:50:20.819676256Z", - "deposit_end_time": "2022-03-30T11:50:20.819676256Z", - "total_deposit": [ - { - "denom": "stake", - "amount": "10000000" - } - ], - "voting_start_time": "2022-03-28T14:25:26.644857113Z", - "voting_end_time": "2022-03-30T14:25:26.644857113Z", - "metadata": "AQ==", - "title": "Proposal Title", - "summary": "Proposal Summary" - } -} -``` - #### proposals The `proposals` endpoint also allows users to query all proposals with optional filters. -Using legacy v1beta1: - -```bash -/cosmos/gov/v1beta1/proposals -``` - -Example: - -```bash -curl localhost:1317/cosmos/gov/v1beta1/proposals -``` - -Example Output: - -```bash -{ - "proposals": [ - { - "proposal_id": "1", - "content": null, - "status": "PROPOSAL_STATUS_VOTING_PERIOD", - "final_tally_result": { - "yes": "0", - "abstain": "0", - "no": "0", - "no_with_veto": "0" - }, - "submit_time": "2022-03-28T11:50:20.819676256Z", - "deposit_end_time": "2022-03-30T11:50:20.819676256Z", - "total_deposit": [ - { - "denom": "stake", - "amount": "10000000" - } - ], - "voting_start_time": "2022-03-28T14:25:26.644857113Z", - "voting_end_time": "2022-03-30T14:25:26.644857113Z" - }, - { - "proposal_id": "2", - "content": null, - "status": "PROPOSAL_STATUS_DEPOSIT_PERIOD", - "final_tally_result": { - "yes": "0", - "abstain": "0", - "no": "0", - "no_with_veto": "0" - }, - "submit_time": "2022-03-28T14:02:41.165025015Z", - "deposit_end_time": "2022-03-30T14:02:41.165025015Z", - "total_deposit": [ - { - "denom": "stake", - "amount": "10" - } - ], - "voting_start_time": "0001-01-01T00:00:00Z", - "voting_end_time": "0001-01-01T00:00:00Z" - } - ], - "pagination": { - "next_key": null, - "total": "2" - } -} -``` - -Using v1: ```bash /cosmos/gov/v1/proposals @@ -1975,126 +1209,10 @@ Example: curl localhost:1317/cosmos/gov/v1/proposals ``` -Example Output: - -```bash -{ - "proposals": [ - { - "id": "1", - "messages": [ - { - "@type": "/cosmos.bank.v1beta1.MsgSend", - "from_address": "cosmos1..", - "to_address": "cosmos1..", - "amount": [ - { - "denom": "stake", - "amount": "10" - } - ] - } - ], - "status": "PROPOSAL_STATUS_VOTING_PERIOD", - "final_tally_result": { - "yes_count": "0", - "abstain_count": "0", - "no_count": "0", - "no_with_veto_count": "0" - }, - "submit_time": "2022-03-28T11:50:20.819676256Z", - "deposit_end_time": "2022-03-30T11:50:20.819676256Z", - "total_deposit": [ - { - "denom": "stake", - "amount": "10000000010" - } - ], - "voting_start_time": "2022-03-28T14:25:26.644857113Z", - "voting_end_time": "2022-03-30T14:25:26.644857113Z", - "metadata": "AQ==", - "title": "Proposal Title", - "summary": "Proposal Summary" - }, - { - "id": "2", - "messages": [ - { - "@type": "/cosmos.bank.v1beta1.MsgSend", - "from_address": "cosmos1..", - "to_address": "cosmos1..", - "amount": [ - { - "denom": "stake", - "amount": "10" - } - ] - } - ], - "status": "PROPOSAL_STATUS_DEPOSIT_PERIOD", - "final_tally_result": { - "yes_count": "0", - "abstain_count": "0", - "no_count": "0", - "no_with_veto_count": "0" - }, - "submit_time": "2022-03-28T14:02:41.165025015Z", - "deposit_end_time": "2022-03-30T14:02:41.165025015Z", - "total_deposit": [ - { - "denom": "stake", - "amount": "10" - } - ], - "voting_start_time": null, - "voting_end_time": null, - "metadata": "AQ==", - "title": "Proposal Title", - "summary": "Proposal Summary" - } - ], - "pagination": { - "next_key": null, - "total": "2" - } -} -``` - #### voter vote The `votes` endpoint allows users to query a vote for a given proposal. -Using legacy v1beta1: - -```bash -/cosmos/gov/v1beta1/proposals/{proposal_id}/votes/{voter} -``` - -Example: - -```bash -curl localhost:1317/cosmos/gov/v1beta1/proposals/1/votes/cosmos1.. -``` - -Example Output: - -```bash -{ - "vote": { - "proposal_id": "1", - "voter": "cosmos1..", - "option": "VOTE_OPTION_YES", - "options": [ - { - "option": "VOTE_OPTION_YES", - "weight": "1.000000000000000000" - } - ] - } -} -``` - -Using v1: ```bash /cosmos/gov/v1/proposals/{proposal_id}/votes/{voter} @@ -2106,66 +1224,10 @@ Example: curl localhost:1317/cosmos/gov/v1/proposals/1/votes/cosmos1.. ``` -Example Output: - -```bash -{ - "vote": { - "proposal_id": "1", - "voter": "cosmos1..", - "options": [ - { - "option": "VOTE_OPTION_YES", - "weight": "1.000000000000000000" - } - ], - "metadata": "" - } -} -``` - #### votes The `votes` endpoint allows users to query all votes for a given proposal. -Using legacy v1beta1: - -```bash -/cosmos/gov/v1beta1/proposals/{proposal_id}/votes -``` - -Example: - -```bash -curl localhost:1317/cosmos/gov/v1beta1/proposals/1/votes -``` - -Example Output: - -```bash -{ - "votes": [ - { - "proposal_id": "1", - "voter": "cosmos1..", - "option": "VOTE_OPTION_YES", - "options": [ - { - "option": "VOTE_OPTION_YES", - "weight": "1.000000000000000000" - } - ] - } - ], - "pagination": { - "next_key": null, - "total": "1" - } -} -``` - -Using v1: - ```bash /cosmos/gov/v1/proposals/{proposal_id}/votes ``` @@ -2176,58 +1238,10 @@ Example: curl localhost:1317/cosmos/gov/v1/proposals/1/votes ``` -Example Output: - -```bash -{ - "votes": [ - { - "proposal_id": "1", - "voter": "cosmos1..", - "options": [ - { - "option": "VOTE_OPTION_YES", - "weight": "1.000000000000000000" - } - ], - "metadata": "" - } - ], - "pagination": { - "next_key": null, - "total": "1" - } -} -``` - #### params The `params` endpoint allows users to query all parameters for the `gov` module. -Using legacy v1beta1: - -```bash -/cosmos/gov/v1beta1/params/{params_type} -``` - -Example: - -```bash -curl localhost:1317/cosmos/gov/v1beta1/params/voting -``` - -Example Output: - -```bash -{ - "voting_params": { - "voting_period": "172800s" - }, -} -``` - -Using v1: - ```bash /cosmos/gov/v1/params/{params_type} ``` @@ -2238,63 +1252,12 @@ Example: curl localhost:1317/cosmos/gov/v1/params/voting ``` -Example Output: - -```bash -{ - "voting_params": { - "voting_period": "172800s" - }, - "deposit_params": { - "min_deposit": [ - ], - "max_deposit_period": "0s" - }, - "tally_params": { - "quorum": "0.000000000000000000", - "threshold": "0.000000000000000000", - "veto_threshold": "0.000000000000000000" - } -} -``` - Note: `params_type` are deprecated in v1 since all params are stored in Params. #### deposits The `deposits` endpoint allows users to query a deposit for a given proposal from a given depositor. -Using legacy v1beta1: - -```bash -/cosmos/gov/v1beta1/proposals/{proposal_id}/deposits/{depositor} -``` - -Example: - -```bash -curl localhost:1317/cosmos/gov/v1beta1/proposals/1/deposits/cosmos1.. -``` - -Example Output: - -```bash -{ - "deposit": { - "proposal_id": "1", - "depositor": "cosmos1..", - "amount": [ - { - "denom": "stake", - "amount": "10000000" - } - ] - } -} -``` - -Using v1: - ```bash /cosmos/gov/v1/proposals/{proposal_id}/deposits/{depositor} ``` @@ -2305,64 +1268,10 @@ Example: curl localhost:1317/cosmos/gov/v1/proposals/1/deposits/cosmos1.. ``` -Example Output: - -```bash -{ - "deposit": { - "proposal_id": "1", - "depositor": "cosmos1..", - "amount": [ - { - "denom": "stake", - "amount": "10000000" - } - ] - } -} -``` - #### proposal deposits The `deposits` endpoint allows users to query all deposits for a given proposal. -Using legacy v1beta1: - -```bash -/cosmos/gov/v1beta1/proposals/{proposal_id}/deposits -``` - -Example: - -```bash -curl localhost:1317/cosmos/gov/v1beta1/proposals/1/deposits -``` - -Example Output: - -```bash -{ - "deposits": [ - { - "proposal_id": "1", - "depositor": "cosmos1..", - "amount": [ - { - "denom": "stake", - "amount": "10000000" - } - ] - } - ], - "pagination": { - "next_key": null, - "total": "1" - } -} -``` - -Using v1: - ```bash /cosmos/gov/v1/proposals/{proposal_id}/deposits ``` @@ -2373,60 +1282,10 @@ Example: curl localhost:1317/cosmos/gov/v1/proposals/1/deposits ``` -Example Output: - -```bash -{ - "deposits": [ - { - "proposal_id": "1", - "depositor": "cosmos1..", - "amount": [ - { - "denom": "stake", - "amount": "10000000" - } - ] - } - ], - "pagination": { - "next_key": null, - "total": "1" - } -} -``` - #### tally The `tally` endpoint allows users to query the tally of a given proposal. -Using legacy v1beta1: - -```bash -/cosmos/gov/v1beta1/proposals/{proposal_id}/tally -``` - -Example: - -```bash -curl localhost:1317/cosmos/gov/v1beta1/proposals/1/tally -``` - -Example Output: - -```bash -{ - "tally": { - "yes": "1000000", - "abstain": "0", - "no": "0", - "no_with_veto": "0" - } -} -``` - -Using v1: - ```bash /cosmos/gov/v1/proposals/{proposal_id}/tally ``` @@ -2436,50 +1295,3 @@ Example: ```bash curl localhost:1317/cosmos/gov/v1/proposals/1/tally ``` - -Example Output: - -```bash -{ - "tally": { - "yes": "1000000", - "abstain": "0", - "no": "0", - "no_with_veto": "0" - } -} -``` - -## Metadata - -The gov module has two locations for metadata where users can provide further context about the on-chain actions they are taking. By default all metadata fields have a 255 character length field where metadata can be stored in json format, either on-chain or off-chain depending on the amount of data required. Here we provide a recommendation for the json structure and where the data should be stored. There are two important factors in making these recommendations. First, that the gov and group modules are consistent with one another, note the number of proposals made by all groups may be quite large. Second, that client applications such as block explorers and governance interfaces have confidence in the consistency of metadata structure across chains. - -### Proposal - -Location: off-chain as json object stored on IPFS (mirrors [group proposal](../group/README.md#metadata)) - -```json -{ - "title": "", - "authors": [""], - "summary": "", - "details": "", - "proposal_forum_url": "", - "vote_option_context": "", -} -``` - -:::note -The `authors` field is an array of strings, this is to allow for multiple authors to be listed in the metadata. -In v0.46, the `authors` field is a comma-separated string. Frontends are encouraged to support both formats for backwards compatibility. -::: - -### Vote - -Location: on-chain as json within 255 character limit (mirrors [group vote](../group/README.md#metadata)) - -```json -{ - "justification": "", -} -``` diff --git a/x/gov/client/cli/prompt_test.go b/x/gov/client/cli/prompt_test.go index 89110536d7e1..359c9dea5b53 100644 --- a/x/gov/client/cli/prompt_test.go +++ b/x/gov/client/cli/prompt_test.go @@ -72,7 +72,6 @@ func TestPromptParseInteger(t *testing.T) { } for _, tc := range values { - tc := tc t.Run(tc.in, func(t *testing.T) { origStdin := readline.Stdin defer func() { diff --git a/x/gov/client/cli/tx_test.go b/x/gov/client/cli/tx_test.go index f0933d9ebedd..9bb1eddc19d5 100644 --- a/x/gov/client/cli/tx_test.go +++ b/x/gov/client/cli/tx_test.go @@ -160,8 +160,6 @@ func (s *CLITestSuite) TestNewCmdSubmitProposal() { } for _, tc := range testCases { - tc := tc - s.Run(tc.name, func() { cmd := cli.NewCmdSubmitProposal() @@ -256,8 +254,6 @@ func (s *CLITestSuite) TestNewCmdSubmitLegacyProposal() { } for _, tc := range testCases { - tc := tc - s.Run(tc.name, func() { cmd := cli.NewCmdSubmitLegacyProposal() @@ -360,7 +356,6 @@ func (s *CLITestSuite) TestNewCmdWeightedVote() { } for _, tc := range testCases { - tc := tc s.Run(tc.name, func() { cmd := cli.NewCmdWeightedVote() out, err := clitestutil.ExecTestCLICmd(s.clientCtx, cmd, tc.args) diff --git a/x/gov/client/utils/query_test.go b/x/gov/client/utils/query_test.go index 1d1b4119915a..3f555f37d90c 100644 --- a/x/gov/client/utils/query_test.go +++ b/x/gov/client/utils/query_test.go @@ -193,8 +193,6 @@ func TestGetPaginatedVotes(t *testing.T) { }, }, } { - tc := tc - t.Run(tc.description, func(t *testing.T) { marshaled := make([][]byte, len(tc.msgs)) clientCtx := client.Context{}. @@ -298,8 +296,6 @@ func TestGetSingleVote(t *testing.T) { }, }, } { - tc := tc - t.Run(tc.description, func(t *testing.T) { marshaled := make([][]byte, len(tc.msgs)) clientCtx := client.Context{}. diff --git a/x/gov/go.mod b/x/gov/go.mod index cf006f093661..f86ae5dcf8c6 100644 --- a/x/gov/go.mod +++ b/x/gov/go.mod @@ -3,10 +3,10 @@ module cosmossdk.io/x/gov go 1.23.1 require ( - cosmossdk.io/api v0.7.5 + cosmossdk.io/api v0.7.6 cosmossdk.io/collections v0.4.0 - cosmossdk.io/core v1.0.0-alpha.2 - cosmossdk.io/core/testing v0.0.0-00010101000000-000000000000 + cosmossdk.io/core v1.0.0-alpha.4 + cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29 cosmossdk.io/depinject v1.0.0 cosmossdk.io/errors v1.0.1 cosmossdk.io/log v1.4.1 @@ -27,16 +27,15 @@ require ( github.com/spf13/cobra v1.8.1 github.com/spf13/pflag v1.0.5 github.com/stretchr/testify v1.9.0 - google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 - google.golang.org/grpc v1.66.2 + google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 + google.golang.org/grpc v1.67.1 google.golang.org/protobuf v1.34.2 - gotest.tools/v3 v3.5.1 ) require ( buf.build/gen/go/cometbft/cometbft/protocolbuffers/go v1.34.2-20240701160653-fedbb9acfd2f.2 // indirect buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.34.2-20240130113600-88ef6483f90f.2 // indirect - cosmossdk.io/schema v0.2.0 // indirect + cosmossdk.io/schema v0.3.1-0.20240930054013-7c6e0388a3f9 // indirect cosmossdk.io/x/tx v0.13.3 // indirect filippo.io/edwards25519 v1.1.0 // indirect github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect @@ -103,7 +102,7 @@ require ( github.com/hashicorp/hcl v1.0.0 // indirect github.com/hashicorp/yamux v0.1.1 // indirect github.com/hdevalence/ed25519consensus v0.2.0 // indirect - github.com/huandu/skiplist v1.2.0 // indirect + github.com/huandu/skiplist v1.2.1 // indirect github.com/iancoleman/strcase v0.3.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jmhodges/levigo v1.0.0 // indirect @@ -126,9 +125,9 @@ require ( github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/client_golang v1.20.3 // indirect + github.com/prometheus/client_golang v1.20.4 // indirect github.com/prometheus/client_model v0.6.1 // indirect - github.com/prometheus/common v0.59.1 // indirect + github.com/prometheus/common v0.60.0 // indirect github.com/prometheus/procfs v0.15.1 // indirect github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect github.com/rogpeppe/go-internal v1.12.0 // indirect @@ -163,9 +162,10 @@ require ( golang.org/x/text v0.18.0 // indirect golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect + gotest.tools/v3 v3.5.1 // indirect pgregory.net/rapid v1.1.0 // indirect sigs.k8s.io/yaml v1.4.0 // indirect ) @@ -176,7 +176,6 @@ replace github.com/cosmos/cosmos-sdk => ../../. replace ( cosmossdk.io/api => ../../api cosmossdk.io/collections => ../../collections - cosmossdk.io/core/testing => ../../core/testing cosmossdk.io/store => ../../store cosmossdk.io/x/bank => ../bank cosmossdk.io/x/protocolpool => ../protocolpool diff --git a/x/gov/go.sum b/x/gov/go.sum index 0fbe110c42af..46e0295dc4b6 100644 --- a/x/gov/go.sum +++ b/x/gov/go.sum @@ -4,8 +4,10 @@ buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.34.2-20240130113600-88e buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.34.2-20240130113600-88ef6483f90f.2/go.mod h1:HqcXMSa5qnNuakaMUo+hWhF51mKbcrZxGl9Vp5EeJXc= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cosmossdk.io/core v1.0.0-alpha.2 h1:epU0Xwces4Rgl5bMhHHkXGaGDcyucNGlC/JDH+Suckg= -cosmossdk.io/core v1.0.0-alpha.2/go.mod h1:abgLjeFLhtuKIYZWSPlVUgQBrKObO7ULV35KYfexE90= +cosmossdk.io/core v1.0.0-alpha.4 h1:9iuroT9ejDYETCsGkzkvs/wAY/5UFl7nCIINFRxyMJY= +cosmossdk.io/core v1.0.0-alpha.4/go.mod h1:3u9cWq1FAVtiiCrDPpo4LhR+9V6k/ycSG4/Y/tREWCY= +cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29 h1:NxxUo0GMJUbIuVg0R70e3cbn9eFTEuMr7ev1AFvypdY= +cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29/go.mod h1:8s2tPeJtSiQuoyPmr2Ag7meikonISO4Fv4MoO8+ORrs= cosmossdk.io/depinject v1.0.0 h1:dQaTu6+O6askNXO06+jyeUAnF2/ssKwrrszP9t5q050= cosmossdk.io/depinject v1.0.0/go.mod h1:zxK/h3HgHoA/eJVtiSsoaRaRA2D5U4cJ5thIG4ssbB8= cosmossdk.io/errors v1.0.1 h1:bzu+Kcr0kS/1DuPBtUFdWjzLqyUuCiyHjyJB6srBV/0= @@ -14,8 +16,8 @@ cosmossdk.io/log v1.4.1 h1:wKdjfDRbDyZRuWa8M+9nuvpVYxrEOwbD/CA8hvhU8QM= cosmossdk.io/log v1.4.1/go.mod h1:k08v0Pyq+gCP6phvdI6RCGhLf/r425UT6Rk/m+o74rU= cosmossdk.io/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE= cosmossdk.io/math v1.3.0/go.mod h1:vnRTxewy+M7BtXBNFybkuhSH4WfedVAAnERHgVFhp3k= -cosmossdk.io/schema v0.2.0 h1:UH5CR1DqUq8yP+5Np8PbvG4YX0zAUsTN2Qk6yThmfMk= -cosmossdk.io/schema v0.2.0/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= +cosmossdk.io/schema v0.3.1-0.20240930054013-7c6e0388a3f9 h1:DmOoS/1PeY6Ih0hAVlJ69kLMUrLV+TCbfICrZtB1vdU= +cosmossdk.io/schema v0.3.1-0.20240930054013-7c6e0388a3f9/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMbk2FiG/kXiLl8BRyzTWDw7gX/Hz7Dd5eDMs= @@ -296,8 +298,8 @@ github.com/hdevalence/ed25519consensus v0.2.0/go.mod h1:w3BHWjwJbFU29IRHL1Iqkw3s github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/huandu/go-assert v1.1.5 h1:fjemmA7sSfYHJD7CUqs9qTwwfdNAx7/j2/ZlHXzNB3c= github.com/huandu/go-assert v1.1.5/go.mod h1:yOLvuqZwmcHIC5rIzrBhT7D3Q9c3GFnd0JrPVhn/06U= -github.com/huandu/skiplist v1.2.0 h1:gox56QD77HzSC0w+Ws3MH3iie755GBJU1OER3h5VsYw= -github.com/huandu/skiplist v1.2.0/go.mod h1:7v3iFjLcSAzO4fN5B8dvebvo/qsfumiLiDXMrPiHF9w= +github.com/huandu/skiplist v1.2.1 h1:dTi93MgjwErA/8idWTzIw4Y1kZsMWx35fmI2c8Rij7w= +github.com/huandu/skiplist v1.2.1/go.mod h1:7v3iFjLcSAzO4fN5B8dvebvo/qsfumiLiDXMrPiHF9w= github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI= github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= @@ -408,8 +410,8 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= -github.com/prometheus/client_golang v1.20.3 h1:oPksm4K8B+Vt35tUhw6GbSNSgVlVSBH0qELP/7u83l4= -github.com/prometheus/client_golang v1.20.3/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_golang v1.20.4 h1:Tgh3Yr67PaOv/uTqloMsCEdeuFTatm5zIq5+qNN23vI= +github.com/prometheus/client_golang v1.20.4/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -418,8 +420,8 @@ github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= -github.com/prometheus/common v0.59.1 h1:LXb1quJHWm1P6wq/U824uxYi4Sg0oGvNeUm1z5dJoX0= -github.com/prometheus/common v0.59.1/go.mod h1:GpWM7dewqmVYcd7SmRaiWVe9SSqjf0UrwnYnpEZNuT0= +github.com/prometheus/common v0.60.0 h1:+V9PAREWNvJMAuJ1x1BaWl9dewMW4YrHZQbx0sJNllA= +github.com/prometheus/common v0.60.0/go.mod h1:h0LYf1R1deLSKtD4Vdg8gy4RuOvENW2J/h19V5NADQw= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/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= @@ -644,10 +646,10 @@ google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEY google.golang.org/genproto v0.0.0-20220314164441-57ef72a4c106/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E= google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de h1:F6qOa9AZTYJXOUEr4jDysRDLrm4PHePlge4v4TGAlxY= google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:VUhTRKeHn9wwcdrk73nvdC9gF178Tzhmt/qyaFcPLSo= -google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 h1:+rdxYoE3E5htTEWIe15GlN6IfvbURM//Jt0mmkmm6ZU= -google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117/go.mod h1:OimBR/bc1wPO9iV4NC2bpyjy3VnAwZh5EBPQdtaE5oo= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:pPJltXNxVzT4pK9yD8vR9X75DaWYYmLGMsEvBfFQZzQ= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= +google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 h1:wKguEg1hsxI2/L3hUYrpo1RVi48K+uTyzKqprwLXsb8= +google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142/go.mod h1:d6be+8HhtEtucleCbxpPW9PA9XwISACu8nvpPqF0BVo= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f h1:cUMEy+8oS78BWIH9OWazBkzbr090Od9tWBNtZHkOhf0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= @@ -658,8 +660,8 @@ google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= -google.golang.org/grpc v1.66.2 h1:3QdXkuq3Bkh7w+ywLdLvM56cmGvQHUMZpiCzt6Rqaoo= -google.golang.org/grpc v1.66.2/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y= +google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E= +google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= 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= diff --git a/x/gov/keeper/abci.go b/x/gov/keeper/abci.go index c0e4120528ab..0ea2860b47a7 100644 --- a/x/gov/keeper/abci.go +++ b/x/gov/keeper/abci.go @@ -20,7 +20,8 @@ import ( // EndBlocker is called every block. func (k Keeper) EndBlocker(ctx context.Context) error { - defer telemetry.ModuleMeasureSince(types.ModuleName, telemetry.Now(), telemetry.MetricKeyEndBlocker) + start := telemetry.Now() + defer telemetry.ModuleMeasureSince(types.ModuleName, start, telemetry.MetricKeyEndBlocker) // delete dead proposals from store and returns theirs deposits. // A proposal is dead when it's inactive and didn't get enough deposit on time to get into voting phase. diff --git a/x/gov/keeper/grpc_query_test.go b/x/gov/keeper/grpc_query_test.go index 0d90df884de6..265726a7f75a 100644 --- a/x/gov/keeper/grpc_query_test.go +++ b/x/gov/keeper/grpc_query_test.go @@ -938,8 +938,6 @@ func (suite *KeeperTestSuite) TestGRPCQueryParams() { } for _, tc := range testCases { - tc := tc - suite.Run(fmt.Sprintf("Case %s", tc.msg), func() { params, err := queryClient.Params(gocontext.Background(), &tc.req) @@ -1008,7 +1006,6 @@ func (suite *KeeperTestSuite) TestGRPCQueryMessagedBasedParams() { } for _, tc := range testCases { - tc := tc suite.Run(fmt.Sprintf("Case %s", tc.msg), func() { params, err := queryClient.MessageBasedParams(suite.ctx, &tc.req) if tc.expErrMsg != "" { diff --git a/x/gov/keeper/msg_server_test.go b/x/gov/keeper/msg_server_test.go index a1460167f227..34d01824d97f 100644 --- a/x/gov/keeper/msg_server_test.go +++ b/x/gov/keeper/msg_server_test.go @@ -2008,7 +2008,6 @@ func (suite *KeeperTestSuite) TestMsgUpdateParams() { } for _, tc := range testCases { - tc := tc suite.Run(tc.name, func() { msg := tc.input() exec := func(updateParams *v1.MsgUpdateParams) error { @@ -2154,7 +2153,6 @@ func (suite *KeeperTestSuite) TestMsgUpdateMessageParams() { } for _, tc := range testCases { - tc := tc suite.Run(tc.name, func() { _, err := suite.msgSrvr.UpdateMessageParams(suite.ctx, tc.input) if tc.expErrMsg != "" { @@ -2308,7 +2306,6 @@ func (suite *KeeperTestSuite) TestMsgSudoExec() { } for _, tc := range testCases { - tc := tc suite.Run(tc.name, func() { _, err := suite.msgSrvr.SudoExec(suite.ctx, tc.input) if tc.expErrMsg != "" { diff --git a/x/gov/migrations/v3/convert_test.go b/x/gov/migrations/v3/convert_test.go index 3b44f9724552..ff93e5474873 100644 --- a/x/gov/migrations/v3/convert_test.go +++ b/x/gov/migrations/v3/convert_test.go @@ -49,7 +49,6 @@ func TestConvertToLegacyProposal(t *testing.T) { for name, tc := range testCases { t.Run(name, func(t *testing.T) { - tc := tc proposal.FinalTallyResult = &tc.tallyResult v1beta1Proposal, err := v3.ConvertToLegacyProposal(proposal) if tc.expErr { @@ -156,8 +155,6 @@ func TestConvertToLegacyTallyResult(t *testing.T) { }, } for name, tc := range testCases { - tc := tc - t.Run(name, func(t *testing.T) { _, err := v3.ConvertToLegacyTallyResult(&tc.tallyResult) if tc.expErr { diff --git a/x/gov/module.go b/x/gov/module.go index 01a66ef07b1d..8fc5f3061aab 100644 --- a/x/gov/module.go +++ b/x/gov/module.go @@ -21,6 +21,7 @@ import ( "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/simsx" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/module" simtypes "github.com/cosmos/cosmos-sdk/types/simulation" @@ -209,27 +210,32 @@ func (AppModule) GenerateGenesisState(simState *module.SimulationState) { simulation.RandomizedGenState(simState) } -// ProposalContents returns all the gov content functions used to -// simulate governance proposals. -func (AppModule) ProposalContents(simState module.SimulationState) []simtypes.WeightedProposalContent { //nolint:staticcheck // used for legacy testing - return simulation.ProposalContents() -} - -// ProposalMsgs returns all the gov msgs used to simulate governance proposals. -func (AppModule) ProposalMsgs(simState module.SimulationState) []simtypes.WeightedProposalMsg { - return simulation.ProposalMsgs() -} - // RegisterStoreDecoder registers a decoder for gov module's types func (am AppModule) RegisterStoreDecoder(sdr simtypes.StoreDecoderRegistry) { sdr[govtypes.StoreKey] = simtypes.NewStoreDecoderFuncFromCollectionsSchema(am.keeper.Schema) } -// WeightedOperations returns the all the gov module operations with their respective weights. -func (am AppModule) WeightedOperations(simState module.SimulationState) []simtypes.WeightedOperation { - return simulation.WeightedOperations( - simState.AppParams, simState.TxConfig, - am.accountKeeper, am.bankKeeper, am.keeper, - simState.ProposalMsgs, simState.LegacyProposalContents, - ) +// ProposalMsgsX returns msgs used for governance proposals for simulations. +func (AppModule) ProposalMsgsX(weights simsx.WeightSource, reg simsx.Registry) { + reg.Add(weights.Get("submit_text_proposal", 5), simulation.TextProposalFactory()) +} + +func (am AppModule) WeightedOperationsX(weights simsx.WeightSource, reg simsx.Registry, proposalMsgIter simsx.WeightedProposalMsgIter, + legacyProposals []simtypes.WeightedProposalContent, //nolint:staticcheck // used for legacy proposal types +) { + // submit proposal for each payload message + for weight, factory := range proposalMsgIter { + // use a ratio so that we don't flood with gov ops + reg.Add(weight/25, simulation.MsgSubmitProposalFactory(am.keeper, factory)) + } + for _, wContent := range legacyProposals { + reg.Add(weights.Get(wContent.AppParamsKey(), uint32(wContent.DefaultWeight())), simulation.MsgSubmitLegacyProposalFactory(am.keeper, wContent.ContentSimulatorFn())) + } + + state := simulation.NewSharedState() + reg.Add(weights.Get("msg_deposit", 100), simulation.MsgDepositFactory(am.keeper, state)) + reg.Add(weights.Get("msg_vote", 67), simulation.MsgVoteFactory(am.keeper, state)) + reg.Add(weights.Get("msg_weighted_vote", 33), simulation.MsgWeightedVoteFactory(am.keeper, state)) + reg.Add(weights.Get("cancel_proposal", 5), simulation.MsgCancelProposalFactory(am.keeper, state)) + reg.Add(weights.Get("legacy_text_proposal", 5), simulation.MsgSubmitLegacyProposalFactory(am.keeper, simulation.SimulateLegacyTextProposalContent)) } diff --git a/x/gov/simulation/genesis.go b/x/gov/simulation/genesis.go index a522593a2b96..26f7bdafa6f9 100644 --- a/x/gov/simulation/genesis.go +++ b/x/gov/simulation/genesis.go @@ -1,8 +1,6 @@ package simulation import ( - "encoding/json" - "fmt" "math/rand" "time" @@ -198,10 +196,5 @@ func RandomizedGenState(simState *module.SimulationState) { ), ) - bz, err := json.MarshalIndent(&govGenesis, "", " ") - if err != nil { - panic(err) - } - fmt.Printf("Selected randomly generated governance parameters:\n%s\n", bz) simState.GenState[types.ModuleName] = simState.Cdc.MustMarshalJSON(govGenesis) } diff --git a/x/gov/simulation/genesis_test.go b/x/gov/simulation/genesis_test.go index 215225085d3a..4f5e70312ff7 100644 --- a/x/gov/simulation/genesis_test.go +++ b/x/gov/simulation/genesis_test.go @@ -100,8 +100,6 @@ func TestRandomizedGenState1(t *testing.T) { } for _, tt := range tests { - tt := tt - require.Panicsf(t, func() { simulation.RandomizedGenState(&tt.simState) }, tt.panicMsg) } } diff --git a/x/gov/simulation/msg_factory.go b/x/gov/simulation/msg_factory.go new file mode 100644 index 000000000000..b1267a9ea262 --- /dev/null +++ b/x/gov/simulation/msg_factory.go @@ -0,0 +1,371 @@ +package simulation + +import ( + "context" + "math" + "math/rand" + "sync/atomic" + "time" + + sdkmath "cosmossdk.io/math" + "cosmossdk.io/x/gov/keeper" + v1 "cosmossdk.io/x/gov/types/v1" + + "github.com/cosmos/cosmos-sdk/simsx" + sdk "github.com/cosmos/cosmos-sdk/types" + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" + "github.com/cosmos/cosmos-sdk/x/simulation" +) + +func MsgDepositFactory(k *keeper.Keeper, sharedState *SharedState) simsx.SimMsgFactoryFn[*v1.MsgDeposit] { + return func(ctx context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter) ([]simsx.SimAccount, *v1.MsgDeposit) { + r := testData.Rand() + proposalID, ok := randomProposalID(r, k, ctx, v1.StatusDepositPeriod, sharedState) + if !ok { + reporter.Skip("no proposal in deposit state") + return nil, nil + } + proposal, err := k.Proposals.Get(ctx, proposalID) + if err != nil { + reporter.Skip(err.Error()) + return nil, nil + } + // calculate deposit amount + deposit := randDeposit(ctx, proposal, k, r, reporter) + if reporter.IsSkipped() { + return nil, nil + } + from := testData.AnyAccount(reporter, simsx.WithLiquidBalanceGTE(deposit)) + return []simsx.SimAccount{from}, v1.NewMsgDeposit(from.AddressBech32, proposalID, sdk.NewCoins(deposit)) + } +} + +func MsgVoteFactory(k *keeper.Keeper, sharedState *SharedState) simsx.SimMsgFactoryFn[*v1.MsgVote] { + return func(ctx context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter) ([]simsx.SimAccount, *v1.MsgVote) { + r := testData.Rand() + proposalID, ok := randomProposalID(r, k, ctx, v1.StatusVotingPeriod, sharedState) + if !ok { + reporter.Skip("no proposal in deposit state") + return nil, nil + } + from := testData.AnyAccount(reporter, simsx.WithSpendableBalance()) + msg := v1.NewMsgVote(from.AddressBech32, proposalID, randomVotingOption(r.Rand), "") + return []simsx.SimAccount{from}, msg + } +} + +func MsgWeightedVoteFactory(k *keeper.Keeper, sharedState *SharedState) simsx.SimMsgFactoryFn[*v1.MsgVoteWeighted] { + return func(ctx context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter) ([]simsx.SimAccount, *v1.MsgVoteWeighted) { + r := testData.Rand() + proposalID, ok := randomProposalID(r, k, ctx, v1.StatusVotingPeriod, sharedState) + if !ok { + reporter.Skip("no proposal in deposit state") + return nil, nil + } + from := testData.AnyAccount(reporter, simsx.WithSpendableBalance()) + msg := v1.NewMsgVoteWeighted(from.AddressBech32, proposalID, randomWeightedVotingOptions(r.Rand), "") + return []simsx.SimAccount{from}, msg + } +} + +func MsgCancelProposalFactory(k *keeper.Keeper, sharedState *SharedState) simsx.SimMsgFactoryFn[*v1.MsgCancelProposal] { + return func(ctx context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter) ([]simsx.SimAccount, *v1.MsgCancelProposal) { + r := testData.Rand() + status := simsx.OneOf(r, []v1.ProposalStatus{v1.StatusDepositPeriod, v1.StatusVotingPeriod}) + proposalID, ok := randomProposalID(r, k, ctx, status, sharedState) + if !ok { + reporter.Skip("no proposal in deposit state") + return nil, nil + } + proposal, err := k.Proposals.Get(ctx, proposalID) + if err != nil { + reporter.Skip(err.Error()) + return nil, nil + } + // is cancellable? copied from keeper + maxCancelPeriodRate := sdkmath.LegacyMustNewDecFromStr(must(k.Params.Get(ctx)).ProposalCancelMaxPeriod) + maxCancelPeriod := time.Duration(float64(proposal.VotingEndTime.Sub(*proposal.VotingStartTime)) * maxCancelPeriodRate.MustFloat64()).Round(time.Second) + if proposal.VotingEndTime.Add(-maxCancelPeriod).Before(simsx.BlockTime(ctx)) { + reporter.Skip("not cancellable anymore") + return nil, nil + } + + from := testData.GetAccount(reporter, proposal.Proposer) + if from.LiquidBalance().Empty() { + reporter.Skip("proposer is broke") + return nil, nil + } + msg := v1.NewMsgCancelProposal(proposalID, from.AddressBech32) + return []simsx.SimAccount{from}, msg + } +} + +func MsgSubmitLegacyProposalFactory(k *keeper.Keeper, contentSimFn simtypes.ContentSimulatorFn) simsx.SimMsgFactoryX { //nolint:staticcheck // used for legacy testing + return simsx.NewSimMsgFactoryWithFutureOps[*v1.MsgSubmitProposal](func(ctx context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter, fOpsReg simsx.FutureOpsRegistry) ([]simsx.SimAccount, *v1.MsgSubmitProposal) { + // 1) submit proposal now + accs := testData.AllAccounts() + content := contentSimFn(testData.Rand().Rand, ctx, accs) + if content == nil { + reporter.Skip("content is nil") + return nil, nil + } + govacc := must(testData.AddressCodec().BytesToString(k.GetGovernanceAccount(ctx).GetAddress())) + contentMsg := must(v1.NewLegacyContent(content, govacc)) + return submitProposalWithVotesScheduled(ctx, k, testData, reporter, fOpsReg, contentMsg) + }) +} + +func MsgSubmitProposalFactory(k *keeper.Keeper, payloadFactory simsx.FactoryMethod) simsx.SimMsgFactoryX { + return simsx.NewSimMsgFactoryWithFutureOps[*v1.MsgSubmitProposal](func(ctx context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter, fOpsReg simsx.FutureOpsRegistry) ([]simsx.SimAccount, *v1.MsgSubmitProposal) { + _, proposalMsg := payloadFactory(ctx, testData, reporter) + return submitProposalWithVotesScheduled(ctx, k, testData, reporter, fOpsReg, proposalMsg) + }) +} + +func submitProposalWithVotesScheduled( + ctx context.Context, + k *keeper.Keeper, + testData *simsx.ChainDataSource, + reporter simsx.SimulationReporter, + fOpsReg simsx.FutureOpsRegistry, + proposalMsgs ...sdk.Msg, +) ([]simsx.SimAccount, *v1.MsgSubmitProposal) { + r := testData.Rand() + expedited := true + // expedited := r.Bool() + params := must(k.Params.Get(ctx)) + minDeposits := params.MinDeposit + if expedited { + minDeposits = params.ExpeditedMinDeposit + } + minDeposit := r.Coin(minDeposits) + + minDepositRatio := must(sdkmath.LegacyNewDecFromStr(params.GetMinDepositRatio())) + threshold := minDeposit.Amount.ToLegacyDec().Mul(minDepositRatio).TruncateInt() + + minDepositPercent := must(sdkmath.LegacyNewDecFromStr(params.MinInitialDepositRatio)) + minAmount := sdkmath.LegacyNewDecFromInt(minDeposit.Amount).Mul(minDepositPercent).TruncateInt() + amount, err := r.PositiveSDKIntn(minDeposit.Amount.Sub(minAmount)) + if err != nil { + reporter.Skip(err.Error()) + return nil, nil + } + if amount.LT(threshold) { + reporter.Skip("below threshold amount for proposal") + return nil, nil + } + deposit := minDeposit + // deposit := sdk.Coin{Amount: amount.Add(minAmount), Denom: minDeposit.Denom} + + proposer := testData.AnyAccount(reporter, simsx.WithLiquidBalanceGTE(deposit)) + if reporter.IsSkipped() || !proposer.LiquidBalance().BlockAmount(deposit) { + return nil, nil + } + proposalType := v1.ProposalType_PROPOSAL_TYPE_STANDARD + if expedited { + proposalType = v1.ProposalType_PROPOSAL_TYPE_EXPEDITED + } + msg, err := v1.NewMsgSubmitProposal( + proposalMsgs, + sdk.Coins{deposit}, + proposer.AddressBech32, + r.StringN(100), + r.StringN(100), + r.StringN(100), + proposalType, + ) + if err != nil { + reporter.Skip("unable to generate a submit proposal msg") + return nil, nil + } + // futureOps + var ( + // The states are: + // column 1: All validators vote + // column 2: 90% vote + // column 3: 75% vote + // column 4: 40% vote + // column 5: 15% vote + // column 6: no one votes + // All columns sum to 100 for simplicity, values chosen by @valardragon semi-arbitrarily, + // feel free to change. + numVotesTransitionMatrix = must(simulation.CreateTransitionMatrix([][]int{ + {20, 10, 0, 0, 0, 0}, + {55, 50, 20, 10, 0, 0}, + {25, 25, 30, 25, 30, 15}, + {0, 15, 30, 25, 30, 30}, + {0, 0, 20, 30, 30, 30}, + {0, 0, 0, 10, 10, 25}, + })) + statePercentageArray = []float64{1, .9, .75, .4, .15, 0} + curNumVotesState = 1 + ) + + // get the submitted proposal ID + proposalID := must(k.ProposalID.Peek(ctx)) + + // 2) Schedule operations for votes + // 2.1) first pick a number of people to vote. + curNumVotesState = numVotesTransitionMatrix.NextState(r.Rand, curNumVotesState) + numVotes := int(math.Ceil(float64(testData.AccountsCount()) * statePercentageArray[curNumVotesState])) + + // 2.2) select who votes and when + whoVotes := r.Perm(testData.AccountsCount()) + + // didntVote := whoVotes[numVotes:] + whoVotes = whoVotes[:numVotes] + votingPeriod := params.VotingPeriod + // future ops so that votes do not flood the sims. + if r.Intn(100) == 1 { // 1% chance + now := simsx.BlockTime(ctx) + for i := 0; i < numVotes; i++ { + var vF simsx.SimMsgFactoryFn[*v1.MsgVote] = func(ctx context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter) ([]simsx.SimAccount, *v1.MsgVote) { + switch p, err := k.Proposals.Get(ctx, proposalID); { + case err != nil: + reporter.Skip(err.Error()) + return nil, nil + case p.Status != v1.ProposalStatus_PROPOSAL_STATUS_VOTING_PERIOD: + reporter.Skip("proposal not in voting period") + return nil, nil + } + voter := testData.AccountAt(reporter, whoVotes[i]) + msg := v1.NewMsgVote(voter.AddressBech32, proposalID, randomVotingOption(r.Rand), "") + return []simsx.SimAccount{voter}, msg + } + whenVote := now.Add(time.Duration(r.Int63n(int64(votingPeriod.Seconds()))) * time.Second) + fOpsReg.Add(whenVote, vF) + } + } + return []simsx.SimAccount{proposer}, msg +} + +// TextProposalFactory returns a random text proposal content. +// A text proposal is a proposal that contains no msgs. +func TextProposalFactory() simsx.SimMsgFactoryFn[sdk.Msg] { + return func(ctx context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter) ([]simsx.SimAccount, sdk.Msg) { + return nil, nil + } +} + +func randDeposit(ctx context.Context, proposal v1.Proposal, k *keeper.Keeper, r *simsx.XRand, reporter simsx.SimulationReporter) sdk.Coin { + params, err := k.Params.Get(ctx) + if err != nil { + reporter.Skipf("gov params: %s", err) + return sdk.Coin{} + } + minDeposits := params.MinDeposit + if proposal.ProposalType == v1.ProposalType_PROPOSAL_TYPE_EXPEDITED { + minDeposits = params.ExpeditedMinDeposit + } + minDeposit := simsx.OneOf(r, minDeposits) + minDepositRatio, err := sdkmath.LegacyNewDecFromStr(params.GetMinDepositRatio()) + if err != nil { + reporter.Skip(err.Error()) + return sdk.Coin{} + } + + threshold := minDeposit.Amount.ToLegacyDec().Mul(minDepositRatio).TruncateInt() + depositAmount, err := r.PositiveSDKIntInRange(threshold, minDeposit.Amount) + if err != nil { + reporter.Skipf("deposit amount: %s", err) + return sdk.Coin{} + } + return sdk.Coin{Denom: minDeposit.Denom, Amount: depositAmount} +} + +// Pick a random proposal ID between the initial proposal ID +// (defined in gov GenesisState) and the latest proposal ID +// that matches a given Status. +// It does not provide a default ID. +func randomProposalID(r *simsx.XRand, k *keeper.Keeper, ctx context.Context, status v1.ProposalStatus, s *SharedState) (proposalID uint64, found bool) { + proposalID, _ = k.ProposalID.Peek(ctx) + if initialProposalID := s.getMinProposalID(); initialProposalID == unsetProposalID { + s.setMinProposalID(proposalID) + } else if initialProposalID < proposalID { + proposalID = r.Uint64InRange(initialProposalID, proposalID) + } + proposal, err := k.Proposals.Get(ctx, proposalID) + if err != nil || proposal.Status != status { + return proposalID, false + } + + return proposalID, true +} + +// Pick a random weighted voting options +func randomWeightedVotingOptions(r *rand.Rand) v1.WeightedVoteOptions { + w1 := r.Intn(100 + 1) + w2 := r.Intn(100 - w1 + 1) + w3 := r.Intn(100 - w1 - w2 + 1) + w4 := 100 - w1 - w2 - w3 + weightedVoteOptions := v1.WeightedVoteOptions{} + if w1 > 0 { + weightedVoteOptions = append(weightedVoteOptions, &v1.WeightedVoteOption{ + Option: v1.OptionYes, + Weight: sdkmath.LegacyNewDecWithPrec(int64(w1), 2).String(), + }) + } + if w2 > 0 { + weightedVoteOptions = append(weightedVoteOptions, &v1.WeightedVoteOption{ + Option: v1.OptionAbstain, + Weight: sdkmath.LegacyNewDecWithPrec(int64(w2), 2).String(), + }) + } + if w3 > 0 { + weightedVoteOptions = append(weightedVoteOptions, &v1.WeightedVoteOption{ + Option: v1.OptionNo, + Weight: sdkmath.LegacyNewDecWithPrec(int64(w3), 2).String(), + }) + } + if w4 > 0 { + weightedVoteOptions = append(weightedVoteOptions, &v1.WeightedVoteOption{ + Option: v1.OptionNoWithVeto, + Weight: sdkmath.LegacyNewDecWithPrec(int64(w4), 2).String(), + }) + } + return weightedVoteOptions +} + +func randomVotingOption(r *rand.Rand) v1.VoteOption { + switch r.Intn(4) { + case 0: + return v1.OptionYes + case 1: + return v1.OptionAbstain + case 2: + return v1.OptionNo + case 3: + return v1.OptionNoWithVeto + default: + panic("invalid vote option") + } +} + +func must[T any](r T, err error) T { + if err != nil { + panic(err) + } + return r +} + +const unsetProposalID = 100000000000000 + +// SharedState shared state between message invocations +type SharedState struct { + minProposalID atomic.Uint64 +} + +// NewSharedState constructor +func NewSharedState() *SharedState { + r := &SharedState{} + r.setMinProposalID(unsetProposalID) + return r +} + +func (s *SharedState) getMinProposalID() uint64 { + return s.minProposalID.Load() +} + +func (s *SharedState) setMinProposalID(id uint64) { + s.minProposalID.Store(id) +} diff --git a/x/gov/simulation/operations.go b/x/gov/simulation/operations.go deleted file mode 100644 index a2749acb8cb3..000000000000 --- a/x/gov/simulation/operations.go +++ /dev/null @@ -1,752 +0,0 @@ -package simulation - -import ( - "math" - "math/rand" - "sync/atomic" - "time" - - sdkmath "cosmossdk.io/math" - "cosmossdk.io/x/gov/keeper" - "cosmossdk.io/x/gov/types" - v1 "cosmossdk.io/x/gov/types/v1" - - "github.com/cosmos/cosmos-sdk/client" - simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" - sdk "github.com/cosmos/cosmos-sdk/types" - simtypes "github.com/cosmos/cosmos-sdk/types/simulation" - "github.com/cosmos/cosmos-sdk/x/simulation" -) - -const unsetProposalID = 100000000000000 - -// Governance message types and routes -var ( - TypeMsgDeposit = sdk.MsgTypeURL(&v1.MsgDeposit{}) - TypeMsgVote = sdk.MsgTypeURL(&v1.MsgVote{}) - TypeMsgVoteWeighted = sdk.MsgTypeURL(&v1.MsgVoteWeighted{}) - TypeMsgSubmitProposal = sdk.MsgTypeURL(&v1.MsgSubmitProposal{}) - TypeMsgCancelProposal = sdk.MsgTypeURL(&v1.MsgCancelProposal{}) -) - -// Simulation operation weights constants -const ( - OpWeightMsgDeposit = "op_weight_msg_deposit" - OpWeightMsgVote = "op_weight_msg_vote" - OpWeightMsgVoteWeighted = "op_weight_msg_weighted_vote" - OpWeightMsgCancelProposal = "op_weight_msg_cancel_proposal" - - DefaultWeightMsgDeposit = 100 - DefaultWeightMsgVote = 67 - DefaultWeightMsgVoteWeighted = 33 - DefaultWeightTextProposal = 5 - DefaultWeightMsgCancelProposal = 5 -) - -// SharedState shared state between message invocations -type SharedState struct { - minProposalID atomic.Uint64 -} - -// NewSharedState constructor -func NewSharedState() *SharedState { - r := &SharedState{} - r.setMinProposalID(unsetProposalID) - return r -} - -func (s *SharedState) getMinProposalID() uint64 { - return s.minProposalID.Load() -} - -func (s *SharedState) setMinProposalID(id uint64) { - s.minProposalID.Store(id) -} - -// WeightedOperations returns all the operations from the module with their respective weights -func WeightedOperations( - appParams simtypes.AppParams, - txGen client.TxConfig, - ak types.AccountKeeper, - bk types.BankKeeper, - k *keeper.Keeper, - wMsgs []simtypes.WeightedProposalMsg, - wContents []simtypes.WeightedProposalContent, //nolint:staticcheck // used for legacy testing -) simulation.WeightedOperations { - var ( - weightMsgDeposit int - weightMsgVote int - weightMsgVoteWeighted int - weightMsgCancelProposal int - ) - - appParams.GetOrGenerate(OpWeightMsgDeposit, &weightMsgDeposit, nil, - func(_ *rand.Rand) { - weightMsgDeposit = DefaultWeightMsgDeposit - }, - ) - - appParams.GetOrGenerate(OpWeightMsgVote, &weightMsgVote, nil, - func(_ *rand.Rand) { - weightMsgVote = DefaultWeightMsgVote - }, - ) - - appParams.GetOrGenerate(OpWeightMsgVoteWeighted, &weightMsgVoteWeighted, nil, - func(_ *rand.Rand) { - weightMsgVoteWeighted = DefaultWeightMsgVoteWeighted - }, - ) - - appParams.GetOrGenerate(OpWeightMsgCancelProposal, &weightMsgCancelProposal, nil, - func(_ *rand.Rand) { - weightMsgCancelProposal = DefaultWeightMsgCancelProposal - }, - ) - - // generate the weighted operations for the proposal msgs - var wProposalOps simulation.WeightedOperations - for _, wMsg := range wMsgs { - wMsg := wMsg // pin variable - var weight int - appParams.GetOrGenerate(wMsg.AppParamsKey(), &weight, nil, - func(_ *rand.Rand) { weight = wMsg.DefaultWeight() }, - ) - - wProposalOps = append( - wProposalOps, - simulation.NewWeightedOperation( - weight, - SimulateMsgSubmitProposal(txGen, ak, bk, k, wMsg.MsgSimulatorFn()), - ), - ) - } - - // generate the weighted operations for the proposal contents - var wLegacyProposalOps simulation.WeightedOperations - for _, wContent := range wContents { - wContent := wContent // pin variable - var weight int - appParams.GetOrGenerate(wContent.AppParamsKey(), &weight, nil, - func(_ *rand.Rand) { weight = wContent.DefaultWeight() }, - ) - - wLegacyProposalOps = append( - wLegacyProposalOps, - simulation.NewWeightedOperation( - weight, - SimulateMsgSubmitLegacyProposal(txGen, ak, bk, k, wContent.ContentSimulatorFn()), - ), - ) - } - state := NewSharedState() - wGovOps := simulation.WeightedOperations{ - simulation.NewWeightedOperation( - weightMsgDeposit, - SimulateMsgDeposit(txGen, ak, bk, k, state), - ), - simulation.NewWeightedOperation( - weightMsgVote, - SimulateMsgVote(txGen, ak, bk, k, state), - ), - simulation.NewWeightedOperation( - weightMsgVoteWeighted, - SimulateMsgVoteWeighted(txGen, ak, bk, k, state), - ), - simulation.NewWeightedOperation( - weightMsgCancelProposal, - SimulateMsgCancelProposal(txGen, ak, bk, k), - ), - } - - return append(wGovOps, append(wProposalOps, wLegacyProposalOps...)...) -} - -// SimulateMsgSubmitProposal simulates creating a msg Submit Proposal -// voting on the proposal, and subsequently slashing the proposal. It is implemented using -// future operations. -func SimulateMsgSubmitProposal( - txGen client.TxConfig, - ak types.AccountKeeper, - bk types.BankKeeper, - k *keeper.Keeper, - msgSim simtypes.MsgSimulatorFnX, -) simtypes.Operation { - return func(r *rand.Rand, app simtypes.AppEntrypoint, ctx sdk.Context, accs []simtypes.Account, chainID string, - ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { - msgs := []sdk.Msg{} - proposalMsg, err := msgSim(ctx, r, accs, ak.AddressCodec()) - if err != nil { - return simtypes.OperationMsg{}, nil, err - } - if proposalMsg != nil { - msgs = append(msgs, proposalMsg) - } - - return simulateMsgSubmitProposal(txGen, ak, bk, k, msgs)(r, app, ctx, accs, chainID) - } -} - -// SimulateMsgSubmitLegacyProposal simulates creating a msg Submit Proposal -// voting on the proposal, and subsequently slashing the proposal. It is implemented using -// future operations. -func SimulateMsgSubmitLegacyProposal( - txGen client.TxConfig, - ak types.AccountKeeper, - bk types.BankKeeper, - k *keeper.Keeper, - contentSim simtypes.ContentSimulatorFn, //nolint:staticcheck // used for legacy testing -) simtypes.Operation { - return func(r *rand.Rand, app simtypes.AppEntrypoint, ctx sdk.Context, accs []simtypes.Account, chainID string, - ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { - // 1) submit proposal now - content := contentSim(r, ctx, accs) - if content == nil { - return simtypes.NoOpMsg(types.ModuleName, TypeMsgSubmitProposal, "content is nil"), nil, nil - } - - govacc, err := ak.AddressCodec().BytesToString(k.GetGovernanceAccount(ctx).GetAddress()) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, TypeMsgSubmitProposal, "error getting governance account address"), nil, err - } - contentMsg, err := v1.NewLegacyContent(content, govacc) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, TypeMsgSubmitProposal, "error converting legacy content into proposal message"), nil, err - } - - return simulateMsgSubmitProposal(txGen, ak, bk, k, []sdk.Msg{contentMsg})(r, app, ctx, accs, chainID) - } -} - -func simulateMsgSubmitProposal( - txGen client.TxConfig, - ak types.AccountKeeper, - bk types.BankKeeper, - k *keeper.Keeper, - proposalMsgs []sdk.Msg, -) simtypes.Operation { - // The states are: - // column 1: All validators vote - // column 2: 90% vote - // column 3: 75% vote - // column 4: 40% vote - // column 5: 15% vote - // column 6: no one votes - // All columns sum to 100 for simplicity, values chosen by @valardragon semi-arbitrarily, - // feel free to change. - numVotesTransitionMatrix, _ := simulation.CreateTransitionMatrix([][]int{ - {20, 10, 0, 0, 0, 0}, - {55, 50, 20, 10, 0, 0}, - {25, 25, 30, 25, 30, 15}, - {0, 15, 30, 25, 30, 30}, - {0, 0, 20, 30, 30, 30}, - {0, 0, 0, 10, 10, 25}, - }) - - statePercentageArray := []float64{1, .9, .75, .4, .15, 0} - curNumVotesState := 1 - - return func( - r *rand.Rand, - app simtypes.AppEntrypoint, - ctx sdk.Context, - accs []simtypes.Account, - chainID string, - ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { - simAccount, _ := simtypes.RandomAcc(r, accs) - expedited := r.Intn(2) == 0 - deposit, skip, err := randomDeposit(r, ctx, ak, bk, k, simAccount.Address, true, expedited) - switch { - case skip: - return simtypes.NoOpMsg(types.ModuleName, TypeMsgSubmitProposal, "skip deposit"), nil, nil - case err != nil: - return simtypes.NoOpMsg(types.ModuleName, TypeMsgSubmitProposal, "unable to generate deposit"), nil, err - } - - proposalType := v1.ProposalType_PROPOSAL_TYPE_STANDARD - if expedited { - proposalType = v1.ProposalType_PROPOSAL_TYPE_EXPEDITED - } - - accAddr, err := ak.AddressCodec().BytesToString(simAccount.Address) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, TypeMsgSubmitProposal, "error getting simAccount address"), nil, err - } - msg, err := v1.NewMsgSubmitProposal( - proposalMsgs, - deposit, - accAddr, - simtypes.RandStringOfLength(r, 100), - simtypes.RandStringOfLength(r, 100), - simtypes.RandStringOfLength(r, 100), - proposalType, - ) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(msg), "unable to generate a submit proposal msg"), nil, err - } - - account := ak.GetAccount(ctx, simAccount.Address) - tx, err := simtestutil.GenSignedMockTx( - r, - txGen, - []sdk.Msg{msg}, - sdk.Coins{sdk.NewInt64Coin(sdk.DefaultBondDenom, 0)}, - simtestutil.DefaultGenTxGas, - chainID, - []uint64{account.GetAccountNumber()}, - []uint64{account.GetSequence()}, - simAccount.PrivKey, - ) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(msg), "unable to generate mock tx"), nil, err - } - - _, _, err = app.SimDeliver(txGen.TxEncoder(), tx) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(msg), "unable to deliver tx"), nil, err - } - - opMsg := simtypes.NewOperationMsg(msg, true, "") - - // get the submitted proposal ID - proposalID, err := k.ProposalID.Peek(ctx) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(msg), "unable to generate proposalID"), nil, err - } - - // 2) Schedule operations for votes - // 2.1) first pick a number of people to vote. - curNumVotesState = numVotesTransitionMatrix.NextState(r, curNumVotesState) - numVotes := int(math.Ceil(float64(len(accs)) * statePercentageArray[curNumVotesState])) - - // 2.2) select who votes and when - whoVotes := r.Perm(len(accs)) - - // didntVote := whoVotes[numVotes:] - whoVotes = whoVotes[:numVotes] - params, _ := k.Params.Get(ctx) - votingPeriod := params.VotingPeriod - var fops []simtypes.FutureOperation - if false { // future ops deactivated because they were not implemented correct in the framework before and flood the system now - fops = make([]simtypes.FutureOperation, numVotes+1) - for i := 0; i < numVotes; i++ { - whenVote := ctx.HeaderInfo().Time.Add(time.Duration(r.Int63n(int64(votingPeriod.Seconds()))) * time.Second) - fops[i] = simtypes.FutureOperation{ - BlockTime: whenVote, - Op: func(r *rand.Rand, app simtypes.AppEntrypoint, ctx sdk.Context, accounts []simtypes.Account, chainID string) (OperationMsg simtypes.OperationMsg, futureOps []simtypes.FutureOperation, err error) { - return operationSimulateMsgVote(txGen, ak, bk, k, accs[whoVotes[i]], int64(proposalID), nil)(r, app, ctx, accounts, chainID) - }, - } - } - } - return opMsg, fops, nil - } -} - -// SimulateMsgDeposit generates a MsgDeposit with random values. -func SimulateMsgDeposit( - txGen client.TxConfig, - ak types.AccountKeeper, - bk types.BankKeeper, - k *keeper.Keeper, - s *SharedState, -) simtypes.Operation { - return func( - r *rand.Rand, app simtypes.AppEntrypoint, ctx sdk.Context, - accs []simtypes.Account, chainID string, - ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { - simAccount, _ := simtypes.RandomAcc(r, accs) - proposalID, ok := randomProposalID(r, k, ctx, v1.StatusDepositPeriod, s) - if !ok { - return simtypes.NoOpMsg(types.ModuleName, TypeMsgDeposit, "unable to generate proposalID"), nil, nil - } - - p, err := k.Proposals.Get(ctx, proposalID) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, TypeMsgDeposit, "unable to get proposal"), nil, err - } - - isExpedited := p.ProposalType == v1.ProposalType_PROPOSAL_TYPE_EXPEDITED - - deposit, skip, err := randomDeposit(r, ctx, ak, bk, k, simAccount.Address, false, isExpedited) - switch { - case skip: - return simtypes.NoOpMsg(types.ModuleName, TypeMsgDeposit, "skip deposit"), nil, nil - case err != nil: - return simtypes.NoOpMsg(types.ModuleName, TypeMsgDeposit, "unable to generate deposit"), nil, err - } - - addr, err := ak.AddressCodec().BytesToString(simAccount.Address) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, TypeMsgDeposit, "unable to get simAccount address"), nil, err - } - msg := v1.NewMsgDeposit(addr, proposalID, deposit) - - account := ak.GetAccount(ctx, simAccount.Address) - spendable := bk.SpendableCoins(ctx, account.GetAddress()) - - var fees sdk.Coins - coins, hasNeg := spendable.SafeSub(deposit...) - if !hasNeg { - fees, err = simtypes.RandomFees(r, coins) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(msg), "unable to generate fees"), nil, err - } - } - - txCtx := simulation.OperationInput{ - R: r, - App: app, - TxGen: txGen, - Cdc: nil, - Msg: msg, - Context: ctx, - SimAccount: simAccount, - AccountKeeper: ak, - ModuleName: types.ModuleName, - } - - return simulation.GenAndDeliverTx(txCtx, fees) - } -} - -// SimulateMsgVote generates a MsgVote with random values. -func SimulateMsgVote( - txGen client.TxConfig, - ak types.AccountKeeper, - bk types.BankKeeper, - k *keeper.Keeper, - s *SharedState, -) simtypes.Operation { - return operationSimulateMsgVote(txGen, ak, bk, k, simtypes.Account{}, -1, s) -} - -func operationSimulateMsgVote( - txGen client.TxConfig, - ak types.AccountKeeper, - bk types.BankKeeper, - k *keeper.Keeper, - simAccount simtypes.Account, - proposalIDInt int64, - s *SharedState, -) simtypes.Operation { - return func( - r *rand.Rand, app simtypes.AppEntrypoint, ctx sdk.Context, - accs []simtypes.Account, chainID string, - ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { - if simAccount.Equals(simtypes.Account{}) { - simAccount, _ = simtypes.RandomAcc(r, accs) - } - - var proposalID uint64 - - switch { - case proposalIDInt < 0: - var ok bool - proposalID, ok = randomProposalID(r, k, ctx, v1.StatusVotingPeriod, s) - if !ok { - return simtypes.NoOpMsg(types.ModuleName, TypeMsgVote, "unable to generate proposalID"), nil, nil - } - default: - proposalID = uint64(proposalIDInt) - } - - option := randomVotingOption(r) - addr, err := ak.AddressCodec().BytesToString(simAccount.Address) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, TypeMsgVote, "unable to get simAccount address"), nil, err - } - msg := v1.NewMsgVote(addr, proposalID, option, "") - - account := ak.GetAccount(ctx, simAccount.Address) - spendable := bk.SpendableCoins(ctx, account.GetAddress()) - - txCtx := simulation.OperationInput{ - R: r, - App: app, - TxGen: txGen, - Cdc: nil, - Msg: msg, - Context: ctx, - SimAccount: simAccount, - AccountKeeper: ak, - Bankkeeper: bk, - ModuleName: types.ModuleName, - CoinsSpentInMsg: spendable, - } - - return simulation.GenAndDeliverTxWithRandFees(txCtx) - } -} - -// SimulateMsgVoteWeighted generates a MsgVoteWeighted with random values. -func SimulateMsgVoteWeighted( - txGen client.TxConfig, - ak types.AccountKeeper, - bk types.BankKeeper, - k *keeper.Keeper, - s *SharedState, -) simtypes.Operation { - return operationSimulateMsgVoteWeighted(txGen, ak, bk, k, simtypes.Account{}, -1, s) -} - -func operationSimulateMsgVoteWeighted( - txGen client.TxConfig, - ak types.AccountKeeper, - bk types.BankKeeper, - k *keeper.Keeper, - simAccount simtypes.Account, - proposalIDInt int64, - s *SharedState, -) simtypes.Operation { - return func( - r *rand.Rand, app simtypes.AppEntrypoint, ctx sdk.Context, - accs []simtypes.Account, chainID string, - ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { - if simAccount.Equals(simtypes.Account{}) { - simAccount, _ = simtypes.RandomAcc(r, accs) - } - - var proposalID uint64 - - switch { - case proposalIDInt < 0: - var ok bool - proposalID, ok = randomProposalID(r, k, ctx, v1.StatusVotingPeriod, s) - if !ok { - return simtypes.NoOpMsg(types.ModuleName, TypeMsgVoteWeighted, "unable to generate proposalID"), nil, nil - } - default: - proposalID = uint64(proposalIDInt) - } - - options := randomWeightedVotingOptions(r) - addr, err := ak.AddressCodec().BytesToString(simAccount.Address) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, TypeMsgVoteWeighted, "unable to get simAccount address"), nil, err - } - msg := v1.NewMsgVoteWeighted(addr, proposalID, options, "") - - account := ak.GetAccount(ctx, simAccount.Address) - spendable := bk.SpendableCoins(ctx, account.GetAddress()) - - txCtx := simulation.OperationInput{ - R: r, - App: app, - TxGen: txGen, - Cdc: nil, - Msg: msg, - Context: ctx, - SimAccount: simAccount, - AccountKeeper: ak, - Bankkeeper: bk, - ModuleName: types.ModuleName, - CoinsSpentInMsg: spendable, - } - - return simulation.GenAndDeliverTxWithRandFees(txCtx) - } -} - -// SimulateMsgCancelProposal generates a MsgCancelProposal. -func SimulateMsgCancelProposal(txGen client.TxConfig, ak types.AccountKeeper, bk types.BankKeeper, k *keeper.Keeper) simtypes.Operation { - return func( - r *rand.Rand, app simtypes.AppEntrypoint, ctx sdk.Context, - accs []simtypes.Account, chainID string, - ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { - simAccount := accs[0] - proposal := randomProposal(r, k, ctx) - if proposal == nil { - return simtypes.NoOpMsg(types.ModuleName, TypeMsgCancelProposal, "no proposals found"), nil, nil - } - - proposerAddr, err := ak.AddressCodec().BytesToString(simAccount.Address) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, TypeMsgCancelProposal, "invalid proposer"), nil, err - } - if proposal.Proposer != proposerAddr { - return simtypes.NoOpMsg(types.ModuleName, TypeMsgCancelProposal, "invalid proposer"), nil, nil - } - - if (proposal.Status != v1.StatusDepositPeriod) && (proposal.Status != v1.StatusVotingPeriod) { - return simtypes.NoOpMsg(types.ModuleName, TypeMsgCancelProposal, "invalid proposal status"), nil, nil - } - - account := ak.GetAccount(ctx, simAccount.Address) - spendable := bk.SpendableCoins(ctx, account.GetAddress()) - - accAddr, err := ak.AddressCodec().BytesToString(account.GetAddress()) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, TypeMsgCancelProposal, "could not get account address"), nil, err - } - msg := v1.NewMsgCancelProposal(proposal.Id, accAddr) - - txCtx := simulation.OperationInput{ - R: r, - App: app, - TxGen: txGen, - Cdc: nil, - Msg: msg, - Context: ctx, - SimAccount: simAccount, - AccountKeeper: ak, - Bankkeeper: bk, - ModuleName: types.ModuleName, - CoinsSpentInMsg: spendable, - } - - return simulation.GenAndDeliverTxWithRandFees(txCtx) - } -} - -// Pick a random deposit with a random denomination with a -// deposit amount between (0, min(balance, minDepositAmount)) -// This is to simulate multiple users depositing to get the -// proposal above the minimum deposit amount -func randomDeposit( - r *rand.Rand, - ctx sdk.Context, - ak types.AccountKeeper, - bk types.BankKeeper, - k *keeper.Keeper, - addr sdk.AccAddress, - useMinAmount bool, - expedited bool, -) (deposit sdk.Coins, skip bool, err error) { - account := ak.GetAccount(ctx, addr) - spendable := bk.SpendableCoins(ctx, account.GetAddress()) - - if spendable.Empty() { - return nil, true, nil // skip - } - - params, _ := k.Params.Get(ctx) - minDeposit := params.MinDeposit - if expedited { - minDeposit = params.ExpeditedMinDeposit - } - denomIndex := r.Intn(len(minDeposit)) - denom := minDeposit[denomIndex].Denom - - spendableBalance := spendable.AmountOf(denom) - if spendableBalance.IsZero() { - return nil, true, nil - } - - minDepositAmount := minDeposit[denomIndex].Amount - - minDepositRatio, err := sdkmath.LegacyNewDecFromStr(params.GetMinDepositRatio()) - if err != nil { - return nil, false, err - } - - threshold := minDepositAmount.ToLegacyDec().Mul(minDepositRatio).TruncateInt() - - minAmount := sdkmath.ZeroInt() - if useMinAmount { - minDepositPercent, err := sdkmath.LegacyNewDecFromStr(params.MinInitialDepositRatio) - if err != nil { - return nil, false, err - } - - minAmount = sdkmath.LegacyNewDecFromInt(minDepositAmount).Mul(minDepositPercent).TruncateInt() - } - - amount, err := simtypes.RandPositiveInt(r, minDepositAmount.Sub(minAmount)) - if err != nil { - return nil, false, err - } - amount = amount.Add(minAmount) - - if amount.GT(spendableBalance) || amount.LT(threshold) { - return nil, true, nil - } - - return sdk.Coins{sdk.NewCoin(denom, amount)}, false, nil -} - -// randomProposal returns a random proposal stored in state -func randomProposal(r *rand.Rand, k *keeper.Keeper, ctx sdk.Context) *v1.Proposal { - var proposals []*v1.Proposal - err := k.Proposals.Walk(ctx, nil, func(key uint64, value v1.Proposal) (stop bool, err error) { - proposals = append(proposals, &value) - return false, nil - }) - if err != nil { - panic(err) - } - if len(proposals) == 0 { - return nil - } - randomIndex := r.Intn(len(proposals)) - return proposals[randomIndex] -} - -// Pick a random proposal ID between the initial proposal ID -// (defined in gov GenesisState) and the latest proposal ID -// that matches a given Status. -// It does not provide a default ID. -func randomProposalID(r *rand.Rand, k *keeper.Keeper, ctx sdk.Context, status v1.ProposalStatus, s *SharedState) (proposalID uint64, found bool) { - proposalID, _ = k.ProposalID.Peek(ctx) - if initialProposalID := s.getMinProposalID(); initialProposalID == unsetProposalID { - s.setMinProposalID(proposalID) - } else if initialProposalID < proposalID { - proposalID = uint64(simtypes.RandIntBetween(r, int(initialProposalID), int(proposalID))) - } - proposal, err := k.Proposals.Get(ctx, proposalID) - if err != nil || proposal.Status != status { - return proposalID, false - } - - return proposalID, true -} - -// Pick a random voting option -func randomVotingOption(r *rand.Rand) v1.VoteOption { - switch r.Intn(4) { - case 0: - return v1.OptionYes - case 1: - return v1.OptionAbstain - case 2: - return v1.OptionNo - case 3: - return v1.OptionNoWithVeto - default: - panic("invalid vote option") - } -} - -// Pick a random weighted voting options -func randomWeightedVotingOptions(r *rand.Rand) v1.WeightedVoteOptions { - w1 := r.Intn(100 + 1) - w2 := r.Intn(100 - w1 + 1) - w3 := r.Intn(100 - w1 - w2 + 1) - w4 := 100 - w1 - w2 - w3 - weightedVoteOptions := v1.WeightedVoteOptions{} - if w1 > 0 { - weightedVoteOptions = append(weightedVoteOptions, &v1.WeightedVoteOption{ - Option: v1.OptionYes, - Weight: sdkmath.LegacyNewDecWithPrec(int64(w1), 2).String(), - }) - } - if w2 > 0 { - weightedVoteOptions = append(weightedVoteOptions, &v1.WeightedVoteOption{ - Option: v1.OptionAbstain, - Weight: sdkmath.LegacyNewDecWithPrec(int64(w2), 2).String(), - }) - } - if w3 > 0 { - weightedVoteOptions = append(weightedVoteOptions, &v1.WeightedVoteOption{ - Option: v1.OptionNo, - Weight: sdkmath.LegacyNewDecWithPrec(int64(w3), 2).String(), - }) - } - if w4 > 0 { - weightedVoteOptions = append(weightedVoteOptions, &v1.WeightedVoteOption{ - Option: v1.OptionNoWithVeto, - Weight: sdkmath.LegacyNewDecWithPrec(int64(w4), 2).String(), - }) - } - return weightedVoteOptions -} diff --git a/x/gov/simulation/proposals.go b/x/gov/simulation/proposals.go index c53d024b13a5..471b51d6ebec 100644 --- a/x/gov/simulation/proposals.go +++ b/x/gov/simulation/proposals.go @@ -4,51 +4,15 @@ import ( "context" "math/rand" - coreaddress "cosmossdk.io/core/address" "cosmossdk.io/x/gov/types/v1beta1" - sdk "github.com/cosmos/cosmos-sdk/types" simtypes "github.com/cosmos/cosmos-sdk/types/simulation" - "github.com/cosmos/cosmos-sdk/x/simulation" ) -// OpWeightSubmitTextProposal app params key for text proposal -const OpWeightSubmitTextProposal = "op_weight_submit_text_proposal" - -// ProposalMsgs defines the module weighted proposals' contents -func ProposalMsgs() []simtypes.WeightedProposalMsg { - return []simtypes.WeightedProposalMsg{ - simulation.NewWeightedProposalMsgX( - OpWeightSubmitTextProposal, - DefaultWeightTextProposal, - SimulateTextProposal, - ), - } -} - -// SimulateTextProposal returns a random text proposal content. -// A text proposal is a proposal that contains no msgs. -func SimulateTextProposal(_ context.Context, r *rand.Rand, _ []simtypes.Account, _ coreaddress.Codec) (sdk.Msg, error) { - return nil, nil -} - -// ProposalContents defines the module weighted proposals' contents -// -//nolint:staticcheck // used for legacy testing -func ProposalContents() []simtypes.WeightedProposalContent { - return []simtypes.WeightedProposalContent{ - simulation.NewWeightedProposalContent( - OpWeightMsgDeposit, - DefaultWeightTextProposal, - SimulateLegacyTextProposalContent, - ), - } -} - -// SimulateTextProposalContent returns a random text proposal content. +// SimulateLegacyTextProposalContent returns a random text proposal content. // //nolint:staticcheck // used for legacy testing -func SimulateLegacyTextProposalContent(r *rand.Rand, _ sdk.Context, _ []simtypes.Account) simtypes.Content { +func SimulateLegacyTextProposalContent(r *rand.Rand, _ context.Context, _ []simtypes.Account) simtypes.Content { return v1beta1.NewTextProposal( simtypes.RandStringOfLength(r, 140), simtypes.RandStringOfLength(r, 5000), diff --git a/x/gov/simulation/proposals_test.go b/x/gov/simulation/proposals_test.go deleted file mode 100644 index 939103c75ea9..000000000000 --- a/x/gov/simulation/proposals_test.go +++ /dev/null @@ -1,63 +0,0 @@ -package simulation_test - -import ( - "context" - "math/rand" - "testing" - - "gotest.tools/v3/assert" - - "cosmossdk.io/x/gov/simulation" - - codectestutil "github.com/cosmos/cosmos-sdk/codec/testutil" - sdk "github.com/cosmos/cosmos-sdk/types" - simtypes "github.com/cosmos/cosmos-sdk/types/simulation" -) - -func TestProposalMsgs(t *testing.T) { - // initialize parameters - s := rand.NewSource(1) - r := rand.New(s) - - accounts := simtypes.RandomAccounts(r, 3) - - // execute ProposalMsgs function - weightedProposalMsgs := simulation.ProposalMsgs() - assert.Assert(t, len(weightedProposalMsgs) == 1) - - w0 := weightedProposalMsgs[0] - - // tests w0 interface: - assert.Equal(t, simulation.OpWeightSubmitTextProposal, w0.AppParamsKey()) - assert.Equal(t, simulation.DefaultWeightTextProposal, w0.DefaultWeight()) - - msg, err := w0.MsgSimulatorFn()(context.Background(), r, accounts, codectestutil.CodecOptions{}.GetAddressCodec()) - assert.NilError(t, err) - assert.Assert(t, msg == nil) -} - -func TestProposalContents(t *testing.T) { - // initialize parameters - s := rand.NewSource(1) - r := rand.New(s) - - ctx := sdk.NewContext(nil, true, nil) - accounts := simtypes.RandomAccounts(r, 3) - - // execute ProposalContents function - weightedProposalContent := simulation.ProposalContents() - assert.Assert(t, len(weightedProposalContent) == 1) - - w0 := weightedProposalContent[0] - - // tests w0 interface: - assert.Equal(t, simulation.OpWeightMsgDeposit, w0.AppParamsKey()) - assert.Equal(t, simulation.DefaultWeightTextProposal, w0.DefaultWeight()) - - content := w0.ContentSimulatorFn()(r, ctx, accounts) - - assert.Equal(t, "NxImpptHBIFDQfnxaTiOBJUgNzvqHbVcVJYlIFWFlzFqqRTTyFzDUMntPzyRamUFqeJAEaSHIuUHZoTWDjWXsYxYvwXwXZEsjRQKgKMselyUqWXMbHzRNDHnMzhWSirUgVggjiBxtWDfhzPDgrorEoNmDEiDdBldYegphCBTYWrmFFXNjxhtygsGBFHTejaKjMsqNdikEzDalEyWRHfJhKqifCKsedVuuJbQMbmRVuIPDluAWGpngjgBjOxuRFwSadayHNIhVVmNWBbfaTOldclxTTLUMvaBnLfwjHTtsKetEIvgrxLijhKJNablmvqpWIWsmhWQAYNLycREypoASHnyKWrxpoNLBJuyCGysZJgXbQAAmSIbGxMFXuwMVGZgBiZWfPWorAfjBeekCFvljHAtVZaTOsRxbPIioNxLTnWUTzGTvaNhplQQPmMADRRDuUIsiBpnGqPheKmLnopieVseFdTSAvOCacxaqFWFuXzsrVZzlGfeRpClwKuGEBujaPrzSLjVIOMvLlWxuznEOXlxbZroBRVEvEfBBAHOECribZNrYiFnzQqQmBnLksmFNAadusWAGltuqYNntgOlgOGwSdDjWdLboWyAWIcCfmpGJTfbljKPriLehwObuszICkaXNUkmeddeeRulbZBXJVLgteiKIfofGdNBregwUPlINQECatDSNXSIuefyMxxoKfcmjHEwbVtFiXtEnLJkLHUghmzFiymrgBChucZgOQUpGGVQEpRtIQjIBxYhtZPgUORdxXNWUMErWrUeriqYJPcgIDgLMWAyuuQnsHncCtjvHmvFbzYErxeunQllYDUVlXaRBveRUKeXwEGJFTSAqZtaBSDGDtzlADCnGjuTmYMJlapRsWfugmjwKEuoXJVpZvlcHeFvVvRRktRVGwzLfKezPEMABZtbLExQIjynSoahmkmoTHefdzFoBHMcQHFkKVHhpNtudPqJrYuQswzFuFHbSmpNltFnYJpvMrAYHFrNouZaanEUGHvbHIUUFTCtZrcpRHwgjblxlDNJWzHdBNpAXKJPHWQdrGYcAHSctgVlqwqHoLfHsXUdStwfefwzqLuKEhmMyYLdbZrcPgYqjNHxPexsruwEGStAneKbWkQDDIlCWBLSiAASNhZqNFlPtfqPJoxKsgMdzjWqLWdqKQuJqWPMvwPQWZUtVMOTMYKJbfdlZsjdsomuScvDmbDkgRualsxDvRJuCAmPOXitIbcyWsKGSdrEunFAOdmXnsuyFVgJqEjbklvmwrUlsxjRSfKZxGcpayDdgoFcnVSutxjRgOSFzPwidAjubMncNweqpbxhXGchpZUxuFDOtpnhNUycJICRYqsPhPSCjPTWZFLkstHWJxvdPEAyEIxXgLwbNOjrgzmaujiBABBIXvcXpLrbcEWNNQsbjvgJFgJkflpRohHUutvnaUqoopuKjTDaemDeSdqbnOzcfJpcTuAQtZoiLZOoAIlboFDAeGmSNwkvObPRvRWQgWkGkxwtPauYgdkmypLjbqhlHJIQTntgWjXwZdOyYEdQRRLfMSdnxqppqUofqLbLQDUjwKVKfZJUJQPsWIPwIVaSTrmKskoAhvmZyJgeRpkaTfGgrJzAigcxtfshmiDCFkuiluqtMOkidknnTBtumyJYlIsWLnCQclqdVmikUoMOPdPWwYbJxXyqUVicNxFxyqJTenNblyyKSdlCbiXxUiYUiMwXZASYfvMDPFgxniSjWaZTjHkqlJvtBsXqwPpyVxnJVGFWhfSxgOcduoxkiopJvFjMmFabrGYeVtTXLhxVUEiGwYUvndjFGzDVntUvibiyZhfMQdMhgsiuysLMiePBNXifRLMsSmXPkwlPloUbJveCvUlaalhZHuvdkCnkSHbMbmOnrfEGPwQiACiPlnihiaOdbjPqPiTXaHDoJXjSlZmltGqNHHNrcKdlFSCdmVOuvDcBLdSklyGJmcLTbSFtALdGlPkqqecJrpLCXNPWefoTJNgEJlyMEPneVaxxduAAEqQpHWZodWyRkDAxzyMnFMcjSVqeRXLqsNyNtQBbuRvunZflWSbbvXXdkyLikYqutQhLPONXbvhcQZJPSWnOulqQaXmbfFxAkqfYeseSHOQidHwbcsOaMnSrrmGjjRmEMQNuknupMxJiIeVjmgZvbmjPIQTEhQFULQLBMPrxcFPvBinaOPYWGvYGRKxLZdwamfRQQFngcdSlvwjfaPbURasIsGJVHtcEAxnIIrhSriiXLOlbEBLXFElXJFGxHJczRBIxAuPKtBisjKBwfzZFagdNmjdwIRvwzLkFKWRTDPxJCmpzHUcrPiiXXHnOIlqNVoGSXZewdnCRhuxeYGPVTfrNTQNOxZmxInOazUYNTNDgzsxlgiVEHPKMfbesvPHUqpNkUqbzeuzfdrsuLDpKHMUbBMKczKKWOdYoIXoPYtEjfOnlQLoGnbQUCuERdEFaptwnsHzTJDsuZkKtzMpFaZobynZdzNydEeJJHDYaQcwUxcqvwfWwNUsCiLvkZQiSfzAHftYgAmVsXgtmcYgTqJIawstRYJrZdSxlfRiqTufgEQVambeZZmaAyRQbcmdjVUZZCgqDrSeltJGXPMgZnGDZqISrGDOClxXCxMjmKqEPwKHoOfOeyGmqWqihqjINXLqnyTesZePQRqaWDQNqpLgNrAUKulklmckTijUltQKuWQDwpLmDyxLppPVMwsmBIpOwQttYFMjgJQZLYFPmxWFLIeZihkRNnkzoypBICIxgEuYsVWGIGRbbxqVasYnstWomJnHwmtOhAFSpttRYYzBmyEtZXiCthvKvWszTXDbiJbGXMcrYpKAgvUVFtdKUfvdMfhAryctklUCEdjetjuGNfJjajZtvzdYaqInKtFPPLYmRaXPdQzxdSQfmZDEVHlHGEGNSPRFJuIfKLLfUmnHxHnRjmzQPNlqrXgifUdzAGKVabYqvcDeYoTYgPsBUqehrBhmQUgTvDnsdpuhUoxskDdppTsYMcnDIPSwKIqhXDCIxOuXrywahvVavvHkPuaenjLmEbMgrkrQLHEAwrhHkPRNvonNQKqprqOFVZKAtpRSpvQUxMoXCMZLSSbnLEFsjVfANdQNQVwTmGxqVjVqRuxREAhuaDrFgEZpYKhwWPEKBevBfsOIcaZKyykQafzmGPLRAKDtTcJxJVgiiuUkmyMYuDUNEUhBEdoBLJnamtLmMJQgmLiUELIhLpiEvpOXOvXCPUeldLFqkKOwfacqIaRcnnZvERKRMCKUkMABbDHytQqQblrvoxOZkwzosQfDKGtIdfcXRJNqlBNwOCWoQBcEWyqrMlYZIAXYJmLfnjoJepgSFvrgajaBAIksoyeHqgqbGvpAstMIGmIhRYGGNPRIfOQKsGoKgxtsidhTaAePRCBFqZgPDWCIkqOJezGVkjfYUCZTlInbxBXwUAVRsxHTQtJFnnpmMvXDYCVlEmnZBKhmmxQOIQzxFWpJQkQoSAYzTEiDWEOsVLNrbfzeHFRyeYATakQQWmFDLPbVMCJcWjFGJjfqCoVzlbNNEsqxdSmNPjTjHYOkuEMFLkXYGaoJlraLqayMeCsTjWNRDPBywBJLAPVkGQqTwApVVwYAetlwSbzsdHWsTwSIcctkyKDuRWYDQikRqsKTMJchrliONJeaZIzwPQrNbTwxsGdwuduvibtYndRwpdsvyCktRHFalvUuEKMqXbItfGcNGWsGzubdPMYayOUOINjpcFBeESdwpdlTYmrPsLsVDhpTzoMegKrytNVZkfJRPuDCUXxSlSthOohmsuxmIZUedzxKmowKOdXTMcEtdpHaPWgIsIjrViKrQOCONlSuazmLuCUjLltOGXeNgJKedTVrrVCpWYWHyVrdXpKgNaMJVjbXxnVMSChdWKuZdqpisvrkBJPoURDYxWOtpjzZoOpWzyUuYNhCzRoHsMjmmWDcXzQiHIyjwdhPNwiPqFxeUfMVFQGImhykFgMIlQEoZCaRoqSBXTSWAeDumdbsOGtATwEdZlLfoBKiTvodQBGOEcuATWXfiinSjPmJKcWgQrTVYVrwlyMWhxqNbCMpIQNoSMGTiWfPTCezUjYcdWppnsYJihLQCqbNLRGgqrwHuIvsazapTpoPZIyZyeeSueJuTIhpHMEJfJpScshJubJGfkusuVBgfTWQoywSSliQQSfbvaHKiLnyjdSbpMkdBgXepoSsHnCQaYuHQqZsoEOmJCiuQUpJkmfyfbIShzlZpHFmLCsbknEAkKXKfRTRnuwdBeuOGgFbJLbDksHVapaRayWzwoYBEpmrlAxrUxYMUekKbpjPNfjUCjhbdMAnJmYQVZBQZkFVweHDAlaqJjRqoQPoOMLhyvYCzqEuQsAFoxWrzRnTVjStPadhsESlERnKhpEPsfDxNvxqcOyIulaCkmPdambLHvGhTZzysvqFauEgkFRItPfvisehFmoBhQqmkfbHVsgfHXDPJVyhwPllQpuYLRYvGodxKjkarnSNgsXoKEMlaSKxKdcVgvOkuLcfLFfdtXGTclqfPOfeoVLbqcjcXCUEBgAGplrkgsmIEhWRZLlGPGCwKWRaCKMkBHTAcypUrYjWwCLtOPVygMwMANGoQwFnCqFrUGMCRZUGJKTZIGPyldsifauoMnJPLTcDHmilcmahlqOELaAUYDBuzsVywnDQfwRLGIWozYaOAilMBcObErwgTDNGWnwQMUgFFSKtPDMEoEQCTKVREqrXZSGLqwTMcxHfWotDllNkIJPMbXzjDVjPOOjCFuIvTyhXKLyhUScOXvYthRXpPfKwMhptXaxIxgqBoUqzrWbaoLTVpQoottZyPFfNOoMioXHRuFwMRYUiKvcWPkrayyTLOCFJlAyslDameIuqVAuxErqFPEWIScKpBORIuZqoXlZuTvAjEdlEWDODFRregDTqGNoFBIHxvimmIZwLfFyKUfEWAnNBdtdzDmTPXtpHRGdIbuucfTjOygZsTxPjf", content.GetDescription()) - assert.Equal(t, "XhSUkMhPjMaxKlMIJMOXcnQfyzeOcbWwNbeHVIkPZBSpYuLyYggwexjxusrBqDOTtGTOWeLrQKjLxzIivHSlcxgdXhhuTSkuxKGLwQvuyNhYFmBZHeAerqyNEUzXPFGkqEGqiQWIXnku", content.GetTitle()) - assert.Equal(t, "gov", content.ProposalRoute()) - assert.Equal(t, "Text", content.ProposalType()) -} diff --git a/x/gov/types/v1/genesis_test.go b/x/gov/types/v1/genesis_test.go index 7040446b06b7..fc26ecd9e2fc 100644 --- a/x/gov/types/v1/genesis_test.go +++ b/x/gov/types/v1/genesis_test.go @@ -175,7 +175,6 @@ func TestValidateGenesis(t *testing.T) { } for _, tc := range testCases { - tc := tc t.Run(tc.name, func(t *testing.T) { err := v1.ValidateGenesis(codec, tc.genesisState()) if tc.expErrMsg != "" { diff --git a/x/group/client/cli/tx_test.go b/x/group/client/cli/tx_test.go index 3707e0f310d1..2ad9ad76479c 100644 --- a/x/group/client/cli/tx_test.go +++ b/x/group/client/cli/tx_test.go @@ -220,8 +220,6 @@ func (s *CLITestSuite) TestTxCreateGroup() { } for _, tc := range testCases { - tc := tc - s.Run(tc.name, func() { ctx := svrcmd.CreateExecuteContext(context.Background()) cmd.SetContext(ctx) @@ -336,8 +334,6 @@ func (s *CLITestSuite) TestTxUpdateGroupMembers() { } for _, tc := range testCases { - tc := tc - s.Run(tc.name, func() { ctx := svrcmd.CreateExecuteContext(context.Background()) @@ -460,8 +456,6 @@ func (s *CLITestSuite) TestTxCreateGroupWithPolicy() { }, } for _, tc := range testCases { - tc := tc - s.Run(tc.name, func() { ctx := svrcmd.CreateExecuteContext(context.Background()) @@ -597,8 +591,6 @@ func (s *CLITestSuite) TestTxCreateGroupPolicy() { } for _, tc := range testCases { - tc := tc - s.Run(tc.name, func() { ctx := svrcmd.CreateExecuteContext(context.Background()) @@ -704,8 +696,6 @@ func (s *CLITestSuite) TestTxUpdateGroupPolicyDecisionPolicy() { } for _, tc := range testCases { - tc := tc - s.Run(tc.name, func() { ctx := svrcmd.CreateExecuteContext(context.Background()) @@ -808,8 +798,6 @@ func (s *CLITestSuite) TestTxSubmitProposal() { } for _, tc := range testCases { - tc := tc - s.Run(tc.name, func() { ctx := svrcmd.CreateExecuteContext(context.Background()) diff --git a/x/group/genesis_test.go b/x/group/genesis_test.go index 1671908fd63f..59753996d0bc 100644 --- a/x/group/genesis_test.go +++ b/x/group/genesis_test.go @@ -743,7 +743,6 @@ func TestGenesisStateValidate(t *testing.T) { }, } for _, tc := range testCases { - tc := tc t.Run(tc.name, func(t *testing.T) { err := tc.genesisState.Validate() if tc.expErr { diff --git a/x/group/go.mod b/x/group/go.mod index 03719f7da3e7..6f83519f4085 100644 --- a/x/group/go.mod +++ b/x/group/go.mod @@ -3,15 +3,15 @@ module cosmossdk.io/x/group go 1.23.1 require ( - cosmossdk.io/api v0.7.5 - cosmossdk.io/core v1.0.0-alpha.2 - cosmossdk.io/core/testing v0.0.0-00010101000000-000000000000 + cosmossdk.io/api v0.7.6 + cosmossdk.io/core v1.0.0-alpha.4 + cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29 cosmossdk.io/depinject v1.0.0 cosmossdk.io/errors v1.0.1 cosmossdk.io/log v1.4.1 cosmossdk.io/math v1.3.0 cosmossdk.io/store v1.1.1-0.20240418092142-896cdf1971bc - cosmossdk.io/x/accounts v0.0.0-20240226161501-23359a0b6d91 + cosmossdk.io/x/accounts v0.0.0-20240913065641-0064ccbce64e cosmossdk.io/x/authz v0.0.0-00010101000000-000000000000 cosmossdk.io/x/bank v0.0.0-20240226161501-23359a0b6d91 cosmossdk.io/x/consensus v0.0.0-00010101000000-000000000000 @@ -28,8 +28,8 @@ require ( github.com/manifoldco/promptui v0.9.0 github.com/spf13/cobra v1.8.1 github.com/stretchr/testify v1.9.0 - google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 - google.golang.org/grpc v1.66.2 + google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 + google.golang.org/grpc v1.67.1 google.golang.org/protobuf v1.34.2 pgregory.net/rapid v1.1.0 ) @@ -38,10 +38,7 @@ require ( buf.build/gen/go/cometbft/cometbft/protocolbuffers/go v1.34.2-20240701160653-fedbb9acfd2f.2 // indirect buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.34.2-20240130113600-88ef6483f90f.2 // indirect cosmossdk.io/collections v0.4.0 // indirect - cosmossdk.io/schema v0.2.0 // indirect - cosmossdk.io/x/accounts/defaults/lockup v0.0.0-20240417181816-5e7aae0db1f5 // indirect - cosmossdk.io/x/accounts/defaults/multisig v0.0.0-00010101000000-000000000000 // indirect - cosmossdk.io/x/distribution v0.0.0-00010101000000-000000000000 // indirect + cosmossdk.io/schema v0.3.1-0.20240930054013-7c6e0388a3f9 // indirect cosmossdk.io/x/epochs v0.0.0-20240522060652-a1ae4c3e0337 // indirect cosmossdk.io/x/tx v0.13.3 // indirect filippo.io/edwards25519 v1.1.0 // indirect @@ -111,7 +108,7 @@ require ( github.com/hashicorp/hcl v1.0.0 // indirect github.com/hashicorp/yamux v0.1.1 // indirect github.com/hdevalence/ed25519consensus v0.2.0 // indirect - github.com/huandu/skiplist v1.2.0 // indirect + github.com/huandu/skiplist v1.2.1 // indirect github.com/iancoleman/strcase v0.3.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jmhodges/levigo v1.0.0 // indirect @@ -134,9 +131,9 @@ require ( github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/client_golang v1.20.3 // indirect + github.com/prometheus/client_golang v1.20.4 // indirect github.com/prometheus/client_model v0.6.1 // indirect - github.com/prometheus/common v0.59.1 // indirect + github.com/prometheus/common v0.60.0 // indirect github.com/prometheus/procfs v0.15.1 // indirect github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect github.com/rogpeppe/go-internal v1.12.0 // indirect @@ -172,7 +169,7 @@ require ( golang.org/x/text v0.18.0 // indirect golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect gotest.tools/v3 v3.5.1 // indirect @@ -185,9 +182,9 @@ replace github.com/cosmos/cosmos-sdk => ../../ replace ( cosmossdk.io/api => ../../api cosmossdk.io/collections => ../../collections - cosmossdk.io/core/testing => ../../core/testing cosmossdk.io/store => ../../store cosmossdk.io/x/accounts => ../accounts + cosmossdk.io/x/accounts/defaults/base => ../accounts/defaults/base cosmossdk.io/x/accounts/defaults/lockup => ../accounts/defaults/lockup cosmossdk.io/x/accounts/defaults/multisig => ../accounts/defaults/multisig cosmossdk.io/x/authz => ../authz diff --git a/x/group/go.sum b/x/group/go.sum index 991c8e5d3928..dbc625fc5f52 100644 --- a/x/group/go.sum +++ b/x/group/go.sum @@ -4,8 +4,10 @@ buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.34.2-20240130113600-88e buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.34.2-20240130113600-88ef6483f90f.2/go.mod h1:HqcXMSa5qnNuakaMUo+hWhF51mKbcrZxGl9Vp5EeJXc= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cosmossdk.io/core v1.0.0-alpha.2 h1:epU0Xwces4Rgl5bMhHHkXGaGDcyucNGlC/JDH+Suckg= -cosmossdk.io/core v1.0.0-alpha.2/go.mod h1:abgLjeFLhtuKIYZWSPlVUgQBrKObO7ULV35KYfexE90= +cosmossdk.io/core v1.0.0-alpha.4 h1:9iuroT9ejDYETCsGkzkvs/wAY/5UFl7nCIINFRxyMJY= +cosmossdk.io/core v1.0.0-alpha.4/go.mod h1:3u9cWq1FAVtiiCrDPpo4LhR+9V6k/ycSG4/Y/tREWCY= +cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29 h1:NxxUo0GMJUbIuVg0R70e3cbn9eFTEuMr7ev1AFvypdY= +cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29/go.mod h1:8s2tPeJtSiQuoyPmr2Ag7meikonISO4Fv4MoO8+ORrs= cosmossdk.io/depinject v1.0.0 h1:dQaTu6+O6askNXO06+jyeUAnF2/ssKwrrszP9t5q050= cosmossdk.io/depinject v1.0.0/go.mod h1:zxK/h3HgHoA/eJVtiSsoaRaRA2D5U4cJ5thIG4ssbB8= cosmossdk.io/errors v1.0.1 h1:bzu+Kcr0kS/1DuPBtUFdWjzLqyUuCiyHjyJB6srBV/0= @@ -14,8 +16,8 @@ cosmossdk.io/log v1.4.1 h1:wKdjfDRbDyZRuWa8M+9nuvpVYxrEOwbD/CA8hvhU8QM= cosmossdk.io/log v1.4.1/go.mod h1:k08v0Pyq+gCP6phvdI6RCGhLf/r425UT6Rk/m+o74rU= cosmossdk.io/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE= cosmossdk.io/math v1.3.0/go.mod h1:vnRTxewy+M7BtXBNFybkuhSH4WfedVAAnERHgVFhp3k= -cosmossdk.io/schema v0.2.0 h1:UH5CR1DqUq8yP+5Np8PbvG4YX0zAUsTN2Qk6yThmfMk= -cosmossdk.io/schema v0.2.0/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= +cosmossdk.io/schema v0.3.1-0.20240930054013-7c6e0388a3f9 h1:DmOoS/1PeY6Ih0hAVlJ69kLMUrLV+TCbfICrZtB1vdU= +cosmossdk.io/schema v0.3.1-0.20240930054013-7c6e0388a3f9/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMbk2FiG/kXiLl8BRyzTWDw7gX/Hz7Dd5eDMs= @@ -298,8 +300,8 @@ github.com/hdevalence/ed25519consensus v0.2.0/go.mod h1:w3BHWjwJbFU29IRHL1Iqkw3s github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/huandu/go-assert v1.1.5 h1:fjemmA7sSfYHJD7CUqs9qTwwfdNAx7/j2/ZlHXzNB3c= github.com/huandu/go-assert v1.1.5/go.mod h1:yOLvuqZwmcHIC5rIzrBhT7D3Q9c3GFnd0JrPVhn/06U= -github.com/huandu/skiplist v1.2.0 h1:gox56QD77HzSC0w+Ws3MH3iie755GBJU1OER3h5VsYw= -github.com/huandu/skiplist v1.2.0/go.mod h1:7v3iFjLcSAzO4fN5B8dvebvo/qsfumiLiDXMrPiHF9w= +github.com/huandu/skiplist v1.2.1 h1:dTi93MgjwErA/8idWTzIw4Y1kZsMWx35fmI2c8Rij7w= +github.com/huandu/skiplist v1.2.1/go.mod h1:7v3iFjLcSAzO4fN5B8dvebvo/qsfumiLiDXMrPiHF9w= github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI= github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= @@ -410,8 +412,8 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= -github.com/prometheus/client_golang v1.20.3 h1:oPksm4K8B+Vt35tUhw6GbSNSgVlVSBH0qELP/7u83l4= -github.com/prometheus/client_golang v1.20.3/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_golang v1.20.4 h1:Tgh3Yr67PaOv/uTqloMsCEdeuFTatm5zIq5+qNN23vI= +github.com/prometheus/client_golang v1.20.4/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -420,8 +422,8 @@ github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= -github.com/prometheus/common v0.59.1 h1:LXb1quJHWm1P6wq/U824uxYi4Sg0oGvNeUm1z5dJoX0= -github.com/prometheus/common v0.59.1/go.mod h1:GpWM7dewqmVYcd7SmRaiWVe9SSqjf0UrwnYnpEZNuT0= +github.com/prometheus/common v0.60.0 h1:+V9PAREWNvJMAuJ1x1BaWl9dewMW4YrHZQbx0sJNllA= +github.com/prometheus/common v0.60.0/go.mod h1:h0LYf1R1deLSKtD4Vdg8gy4RuOvENW2J/h19V5NADQw= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/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= @@ -646,10 +648,10 @@ google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEY google.golang.org/genproto v0.0.0-20220314164441-57ef72a4c106/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E= google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de h1:F6qOa9AZTYJXOUEr4jDysRDLrm4PHePlge4v4TGAlxY= google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:VUhTRKeHn9wwcdrk73nvdC9gF178Tzhmt/qyaFcPLSo= -google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 h1:+rdxYoE3E5htTEWIe15GlN6IfvbURM//Jt0mmkmm6ZU= -google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117/go.mod h1:OimBR/bc1wPO9iV4NC2bpyjy3VnAwZh5EBPQdtaE5oo= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:pPJltXNxVzT4pK9yD8vR9X75DaWYYmLGMsEvBfFQZzQ= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= +google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 h1:wKguEg1hsxI2/L3hUYrpo1RVi48K+uTyzKqprwLXsb8= +google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142/go.mod h1:d6be+8HhtEtucleCbxpPW9PA9XwISACu8nvpPqF0BVo= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f h1:cUMEy+8oS78BWIH9OWazBkzbr090Od9tWBNtZHkOhf0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= @@ -660,8 +662,8 @@ google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= -google.golang.org/grpc v1.66.2 h1:3QdXkuq3Bkh7w+ywLdLvM56cmGvQHUMZpiCzt6Rqaoo= -google.golang.org/grpc v1.66.2/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y= +google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E= +google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= 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= diff --git a/x/group/internal/orm/auto_uint64_test.go b/x/group/internal/orm/auto_uint64_test.go index c6e4870701c1..b61202f504e5 100644 --- a/x/group/internal/orm/auto_uint64_test.go +++ b/x/group/internal/orm/auto_uint64_test.go @@ -48,7 +48,6 @@ func TestAutoUInt64PrefixScan(t *testing.T) { Metadata: metadata, } for _, g := range []testdata.TableModel{t1, t2, t3} { - g := g _, err := tb.Create(store, &g) require.NoError(t, err) } diff --git a/x/group/internal/orm/index_test.go b/x/group/internal/orm/index_test.go index 24ae13b6d480..7e86fc4acba3 100644 --- a/x/group/internal/orm/index_test.go +++ b/x/group/internal/orm/index_test.go @@ -125,7 +125,6 @@ func TestIndexPrefixScan(t *testing.T) { Metadata: []byte("metadata-b"), } for _, g := range []testdata.TableModel{g1, g2, g3} { - g := g _, err := tb.Create(store, &g) require.NoError(t, err) } diff --git a/x/group/internal/orm/iterator.go b/x/group/internal/orm/iterator.go index c2612a4954fc..709a7f7a823c 100644 --- a/x/group/internal/orm/iterator.go +++ b/x/group/internal/orm/iterator.go @@ -298,7 +298,7 @@ func assertDest(dest ModelSlicePtr, destRef, tmpSlice *reflect.Value) (reflect.T protoMarshaler := reflect.TypeOf((*proto.Message)(nil)).Elem() if !elemType.Implements(protoMarshaler) && - !reflect.PtrTo(elemType).Implements(protoMarshaler) { + !reflect.PointerTo(elemType).Implements(protoMarshaler) { return nil, errorsmod.Wrapf(grouperrors.ErrORMInvalidArgument, "unsupported type :%s", elemType) } diff --git a/x/group/internal/orm/iterator_test.go b/x/group/internal/orm/iterator_test.go index bc3c29a57ea7..8ff344d61ea5 100644 --- a/x/group/internal/orm/iterator_test.go +++ b/x/group/internal/orm/iterator_test.go @@ -244,7 +244,6 @@ func TestPaginate(t *testing.T) { } for _, g := range []testdata.TableModel{t1, t2, t3, t4, t5} { - g := g _, err := tb.Create(store, &g) require.NoError(t, err) } diff --git a/x/group/internal/orm/orm_scenario_test.go b/x/group/internal/orm/orm_scenario_test.go index c666f4908116..f32037ccb7f0 100644 --- a/x/group/internal/orm/orm_scenario_test.go +++ b/x/group/internal/orm/orm_scenario_test.go @@ -281,7 +281,6 @@ func TestGasCostsPrimaryKeyTable(t *testing.T) { for i, m := range tms { testCtx.Ctx = testCtx.Ctx.WithGasMeter(storetypes.NewInfiniteGasMeter()) - m := m err = k.primaryKeyTable.Delete(store, &m) require.NoError(t, err) diff --git a/x/group/internal/orm/primary_key_test.go b/x/group/internal/orm/primary_key_test.go index 7d0a77e36578..08cf2b71c560 100644 --- a/x/group/internal/orm/primary_key_test.go +++ b/x/group/internal/orm/primary_key_test.go @@ -48,7 +48,6 @@ func TestPrimaryKeyTablePrefixScan(t *testing.T) { Metadata: metadata, } for _, g := range []testdata.TableModel{t1, t2, t3} { - g := g require.NoError(t, tb.Create(store, &g)) } diff --git a/x/group/keeper/abci.go b/x/group/keeper/abci.go index 563490cbe856..c8d980375496 100644 --- a/x/group/keeper/abci.go +++ b/x/group/keeper/abci.go @@ -2,11 +2,18 @@ package keeper import ( "context" + + "cosmossdk.io/x/group" + + "github.com/cosmos/cosmos-sdk/telemetry" ) // EndBlocker called at every block, updates proposal's `FinalTallyResult` and // prunes expired proposals. func (k Keeper) EndBlocker(ctx context.Context) error { + start := telemetry.Now() + defer telemetry.ModuleMeasureSince(group.ModuleName, start, telemetry.MetricKeyEndBlocker) + if err := k.TallyProposalsAtVPEnd(ctx); err != nil { return err } diff --git a/x/group/keeper/abci_test.go b/x/group/keeper/abci_test.go index 0db99839d51c..9cd40f8edb3d 100644 --- a/x/group/keeper/abci_test.go +++ b/x/group/keeper/abci_test.go @@ -332,7 +332,6 @@ func (s *IntegrationTestSuite) TestEndBlockerPruning() { }, } for msg, spec := range specs { - spec := spec s.Run(msg, func() { proposalID := spec.setupProposal(ctx) @@ -544,7 +543,6 @@ func (s *IntegrationTestSuite) TestEndBlockerTallying() { for msg, spec := range specs { s.Run(msg, func() { - spec := spec pID := spec.preRun(ctx) err := s.groupKeeper.EndBlocker(spec.newCtx) diff --git a/x/group/keeper/grpc_query_test.go b/x/group/keeper/grpc_query_test.go index 84f7a7c31a34..8f90ebd6e917 100644 --- a/x/group/keeper/grpc_query_test.go +++ b/x/group/keeper/grpc_query_test.go @@ -129,8 +129,6 @@ func TestQueryGroupInfo(t *testing.T) { } for _, tc := range testCases { - tc := tc - t.Run(tc.name, func(t *testing.T) { _, err := fixture.queryClient.GroupInfo(fixture.ctx, &tc.req) if tc.expErrMsg != "" { @@ -169,7 +167,6 @@ func TestQueryGroupPolicyInfo(t *testing.T) { } for _, tc := range testCases { - tc := tc t.Run(tc.name, func(t *testing.T) { _, err := fixture.queryClient.GroupPolicyInfo(fixture.ctx, &tc.req) if tc.expErrMsg != "" { @@ -210,7 +207,6 @@ func TestQueryGroupMembers(t *testing.T) { } for _, tc := range testCases { - tc := tc t.Run(tc.name, func(t *testing.T) { resp, err := fixture.queryClient.GroupMembers(fixture.ctx, &tc.req) if tc.expErrMsg != "" { @@ -256,7 +252,6 @@ func TestQueryGroupsByAdmin(t *testing.T) { } for _, tc := range testCases { - tc := tc t.Run(tc.name, func(t *testing.T) { resp, err := fixture.queryClient.GroupsByAdmin(fixture.ctx, &tc.req) if tc.expErrMsg != "" { @@ -297,7 +292,6 @@ func TestQueryGroupPoliciesByGroup(t *testing.T) { } for _, tc := range testCases { - tc := tc t.Run(tc.name, func(t *testing.T) { resp, err := fixture.keeper.GroupPoliciesByGroup(fixture.ctx, &tc.req) if tc.expErrMsg != "" { @@ -343,7 +337,6 @@ func TestQueryGroupPoliciesByAdmin(t *testing.T) { } for _, tc := range testCases { - tc := tc t.Run(tc.name, func(t *testing.T) { resp, err := fixture.keeper.GroupPoliciesByAdmin(fixture.ctx, &tc.req) if tc.expErrMsg != "" { diff --git a/x/group/keeper/keeper.go b/x/group/keeper/keeper.go index b1fc76f920cc..5336704535dd 100644 --- a/x/group/keeper/keeper.go +++ b/x/group/keeper/keeper.go @@ -231,7 +231,7 @@ func NewKeeper(env appmodule.Environment, cdc codec.Codec, accKeeper group.Accou } // GetGroupSequence returns the current value of the group table sequence -func (k Keeper) GetGroupSequence(ctx sdk.Context) uint64 { +func (k Keeper) GetGroupSequence(ctx context.Context) uint64 { return k.groupTable.Sequence().CurVal(k.KVStoreService.OpenKVStore(ctx)) } @@ -379,8 +379,6 @@ func (k Keeper) PruneProposals(ctx context.Context) error { return nil } for _, proposal := range proposals { - proposal := proposal - err := k.pruneProposal(ctx, proposal.Id) if err != nil { return err diff --git a/x/group/keeper/keeper_test.go b/x/group/keeper/keeper_test.go index b07d1136280d..449fe039407f 100644 --- a/x/group/keeper/keeper_test.go +++ b/x/group/keeper/keeper_test.go @@ -115,7 +115,7 @@ func (s *TestSuite) SetupTest() { s.Require().NoError(err) s.setNextAccount() - groupSeq := s.groupKeeper.GetGroupSequence(s.sdkCtx) + groupSeq := s.groupKeeper.GetGroupSequence(s.ctx) s.Require().Equal(groupSeq, uint64(1)) policyRes, err := s.groupKeeper.CreateGroupPolicy(s.ctx, policyReq) @@ -273,7 +273,6 @@ func (s *TestSuite) TestProposalsByVPEnd() { } for msg, spec := range specs { - spec := spec s.Run(msg, func() { pID := spec.preRun(s.sdkCtx) diff --git a/x/group/keeper/msg_server.go b/x/group/keeper/msg_server.go index 79f449d3095f..5191b2dc3b4d 100644 --- a/x/group/keeper/msg_server.go +++ b/x/group/keeper/msg_server.go @@ -820,12 +820,11 @@ func (k Keeper) doTallyAndUpdate(ctx context.Context, p *group.Proposal, groupIn } // Exec executes the messages from a proposal. -func (k Keeper) Exec(goCtx context.Context, msg *group.MsgExec) (*group.MsgExecResponse, error) { +func (k Keeper) Exec(ctx context.Context, msg *group.MsgExec) (*group.MsgExecResponse, error) { if msg.ProposalId == 0 { return nil, errorsmod.Wrap(errors.ErrEmpty, "proposal id") } - ctx := sdk.UnwrapSDKContext(goCtx) proposal, err := k.getProposal(ctx, msg.ProposalId) if err != nil { return nil, err diff --git a/x/group/keeper/msg_server_test.go b/x/group/keeper/msg_server_test.go index a3e3f9274b43..d03f8721d563 100644 --- a/x/group/keeper/msg_server_test.go +++ b/x/group/keeper/msg_server_test.go @@ -169,7 +169,6 @@ func (s *TestSuite) TestCreateGroup() { var seq uint32 = 1 for msg, spec := range specs { - spec := spec s.Run(msg, func() { blockTime := sdk.UnwrapSDKContext(s.ctx).HeaderInfo().Time res, err := s.groupKeeper.CreateGroup(s.ctx, spec.req) @@ -520,7 +519,6 @@ func (s *TestSuite) TestUpdateGroupMembers() { }, } for msg, spec := range specs { - spec := spec s.Run(msg, func() { sdkCtx, _ := s.sdkCtx.CacheContext() _, err := s.groupKeeper.UpdateGroupMembers(sdkCtx, spec.req) @@ -657,7 +655,6 @@ func (s *TestSuite) TestUpdateGroupAdmin() { }, } for msg, spec := range specs { - spec := spec s.Run(msg, func() { _, err := s.groupKeeper.UpdateGroupAdmin(s.ctx, spec.req) if spec.expErr { @@ -727,7 +724,6 @@ func (s *TestSuite) TestUpdateGroupMetadata() { }, } for msg, spec := range specs { - spec := spec s.Run(msg, func() { sdkCtx, _ := s.sdkCtx.CacheContext() _, err := s.groupKeeper.UpdateGroupMetadata(sdkCtx, spec.req) @@ -897,7 +893,6 @@ func (s *TestSuite) TestCreateGroupWithPolicy() { } for msg, spec := range specs { - spec := spec s.Run(msg, func() { s.setNextAccount() err := spec.req.SetDecisionPolicy(spec.policy) @@ -1084,7 +1079,6 @@ func (s *TestSuite) TestCreateGroupPolicy() { }, } for msg, spec := range specs { - spec := spec s.Run(msg, func() { err := spec.req.SetDecisionPolicy(spec.policy) s.Require().NoError(err) @@ -1218,7 +1212,7 @@ func (s *TestSuite) TestUpdateGroupPolicyAdmin() { }, } for msg, spec := range specs { - spec := spec + err := spec.expGroupPolicy.SetDecisionPolicy(policy) s.Require().NoError(err) @@ -1369,7 +1363,7 @@ func (s *TestSuite) TestUpdateGroupPolicyDecisionPolicy() { }, } for msg, spec := range specs { - spec := spec + policyAddr := groupPolicyAddr err := spec.expGroupPolicy.SetDecisionPolicy(spec.policy) s.Require().NoError(err) @@ -1470,7 +1464,7 @@ func (s *TestSuite) TestUpdateGroupPolicyMetadata() { }, } for msg, spec := range specs { - spec := spec + err := spec.expGroupPolicy.SetDecisionPolicy(policy) s.Require().NoError(err) @@ -1877,7 +1871,6 @@ func (s *TestSuite) TestSubmitProposal() { }, } for msg, spec := range specs { - spec := spec s.Run(msg, func() { err := spec.req.SetMsgs(spec.msgs) s.Require().NoError(err) @@ -2002,7 +1995,7 @@ func (s *TestSuite) TestWithdrawProposal() { }, } for msg, spec := range specs { - spec := spec + s.Run(msg, func() { pID := spec.preRun(s.sdkCtx) @@ -2385,7 +2378,6 @@ func (s *TestSuite) TestVote() { }, } for msg, spec := range specs { - spec := spec s.Run(msg, func() { sdkCtx := s.sdkCtx if !spec.srcCtx.IsZero() { @@ -2738,7 +2730,6 @@ func (s *TestSuite) TestExecProposal() { }, } for msg, spec := range specs { - spec := spec s.Run(msg, func() { sdkCtx, _ := s.sdkCtx.CacheContext() proposalID := spec.setupProposal(sdkCtx) @@ -2782,7 +2773,6 @@ func (s *TestSuite) TestExecProposal() { } spec.postRun(sdkCtx) }) - } } @@ -2935,7 +2925,6 @@ func (s *TestSuite) TestExecPrunedProposalsAndVotes() { }, } for msg, spec := range specs { - spec := spec s.Run(msg, func() { sdkCtx, _ := s.sdkCtx.CacheContext() proposalID := spec.setupProposal(sdkCtx) @@ -3343,7 +3332,6 @@ func (s *TestSuite) TestExecProposalsWhenMemberLeavesOrIsUpdated() { }, } for msg, spec := range specs { - spec := spec s.Run(msg, func() { sdkCtx, _ := s.sdkCtx.CacheContext() @@ -3365,7 +3353,7 @@ func (s *TestSuite) TestExecProposalsWhenMemberLeavesOrIsUpdated() { s.setNextAccount() - s.groupKeeper.GetGroupSequence(s.sdkCtx) + s.groupKeeper.GetGroupSequence(s.ctx) policyRes, err := s.groupKeeper.CreateGroupPolicy(s.ctx, policyReq) s.Require().NoError(err) diff --git a/x/group/keeper/tally_test.go b/x/group/keeper/tally_test.go index 80528675144a..0b8575fa1610 100644 --- a/x/group/keeper/tally_test.go +++ b/x/group/keeper/tally_test.go @@ -66,7 +66,6 @@ func (s *TestSuite) TestTally() { } for msg, spec := range specs { - spec := spec s.Run(msg, func() { sdkCtx, _ := s.sdkCtx.CacheContext() pID := spec.setupProposal(sdkCtx) diff --git a/x/group/module/module.go b/x/group/module/module.go index 3f6aecffd827..97b0b40118b7 100644 --- a/x/group/module/module.go +++ b/x/group/module/module.go @@ -19,6 +19,7 @@ import ( sdkclient "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/codec" cdctypes "github.com/cosmos/cosmos-sdk/codec/types" + "github.com/cosmos/cosmos-sdk/simsx" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/module" simtypes "github.com/cosmos/cosmos-sdk/types/simulation" @@ -160,11 +161,21 @@ func (am AppModule) RegisterStoreDecoder(sdr simtypes.StoreDecoderRegistry) { sdr[group.StoreKey] = simulation.NewDecodeStore(am.cdc) } -// WeightedOperations returns the all the gov module operations with their respective weights. -func (am AppModule) WeightedOperations(simState module.SimulationState) []simtypes.WeightedOperation { - return simulation.WeightedOperations( - am.registry, - simState.AppParams, simState.Cdc, simState.TxConfig, - am.accKeeper, am.bankKeeper, am.keeper, am.cdc, - ) +func (am AppModule) WeightedOperationsX(weights simsx.WeightSource, reg simsx.Registry) { + s := simulation.NewSharedState() + // note: using old keys for backwards compatibility + reg.Add(weights.Get("msg_create_group", 100), simulation.MsgCreateGroupFactory()) + reg.Add(weights.Get("msg_update_group_admin", 5), simulation.MsgUpdateGroupAdminFactory(am.keeper, s)) + reg.Add(weights.Get("msg_update_group_metadata", 5), simulation.MsgUpdateGroupMetadataFactory(am.keeper, s)) + reg.Add(weights.Get("msg_update_group_members", 5), simulation.MsgUpdateGroupMembersFactory(am.keeper, s)) + reg.Add(weights.Get("msg_create_group_account", 50), simulation.MsgCreateGroupPolicyFactory(am.keeper, s)) + reg.Add(weights.Get("msg_create_group_with_policy", 50), simulation.MsgCreateGroupWithPolicyFactory()) + reg.Add(weights.Get("msg_update_group_account_admin", 5), simulation.MsgUpdateGroupPolicyAdminFactory(am.keeper, s)) + reg.Add(weights.Get("msg_update_group_account_decision_policy", 5), simulation.MsgUpdateGroupPolicyDecisionPolicyFactory(am.keeper, s)) + reg.Add(weights.Get("msg_update_group_account_metadata", 5), simulation.MsgUpdateGroupPolicyMetadataFactory(am.keeper, s)) + reg.Add(weights.Get("msg_submit_proposal", 2*90), simulation.MsgSubmitProposalFactory(am.keeper, s)) + reg.Add(weights.Get("msg_withdraw_proposal", 20), simulation.MsgWithdrawProposalFactory(am.keeper, s)) + reg.Add(weights.Get("msg_vote", 90), simulation.MsgVoteFactory(am.keeper, s)) + reg.Add(weights.Get("msg_exec", 90), simulation.MsgExecFactory(am.keeper, s)) + reg.Add(weights.Get("msg_leave_group", 5), simulation.MsgLeaveGroupFactory(am.keeper, s)) } diff --git a/x/group/simulation/decoder_test.go b/x/group/simulation/decoder_test.go index ee4a995907c9..2c6cd2d1d670 100644 --- a/x/group/simulation/decoder_test.go +++ b/x/group/simulation/decoder_test.go @@ -78,7 +78,6 @@ func TestDecodeStore(t *testing.T) { } for i, tt := range tests { - i, tt := i, tt t.Run(tt.name, func(t *testing.T) { if tt.expectErr { require.Panics(t, func() { dec(kvPairs.Pairs[i], kvPairs.Pairs[i]) }, tt.name) diff --git a/x/group/simulation/genesis.go b/x/group/simulation/genesis.go index 2049e8a4ac15..f94fe0da18c1 100644 --- a/x/group/simulation/genesis.go +++ b/x/group/simulation/genesis.go @@ -4,7 +4,6 @@ import ( "math/rand" "time" - "cosmossdk.io/core/address" banktypes "cosmossdk.io/x/bank/types" "cosmossdk.io/x/group" @@ -31,14 +30,11 @@ func checkAccExists(acc string, g []*group.GroupMember, lastIndex int) bool { return false } -func getGroups(r *rand.Rand, accounts []simtypes.Account, addressCodec address.Codec) []*group.GroupInfo { +func getGroups(r *rand.Rand, accounts []simtypes.Account) []*group.GroupInfo { groups := make([]*group.GroupInfo, 3) for i := 0; i < 3; i++ { acc, _ := simtypes.RandomAcc(r, accounts) - accAddr, err := addressCodec.BytesToString(acc.Address) - if err != nil { - return nil - } + accAddr := acc.AddressBech32 groups[i] = &group.GroupInfo{ Id: uint64(i + 1), Admin: accAddr, @@ -50,20 +46,14 @@ func getGroups(r *rand.Rand, accounts []simtypes.Account, addressCodec address.C return groups } -func getGroupMembers(r *rand.Rand, accounts []simtypes.Account, addressCodec address.Codec) []*group.GroupMember { +func getGroupMembers(r *rand.Rand, accounts []simtypes.Account) []*group.GroupMember { groupMembers := make([]*group.GroupMember, 3) for i := 0; i < 3; i++ { acc, _ := simtypes.RandomAcc(r, accounts) - accAddr, err := addressCodec.BytesToString(acc.Address) - if err != nil { - return nil - } + accAddr := acc.AddressBech32 for checkAccExists(accAddr, groupMembers, i) { acc, _ = simtypes.RandomAcc(r, accounts) - accAddr, err = addressCodec.BytesToString(acc.Address) - if err != nil { - return nil - } + accAddr = acc.AddressBech32 } groupMembers[i] = &group.GroupMember{ GroupId: uint64(i + 1), @@ -83,11 +73,7 @@ func getGroupPolicies(r *rand.Rand, simState *module.SimulationState) []*group.G usedAccs := make(map[string]bool) for i := 0; i < 3; i++ { acc, _ := simtypes.RandomAcc(r, simState.Accounts) - accAddr, err := simState.AddressCodec.BytesToString(acc.Address) - if err != nil { - return nil - } - if usedAccs[accAddr] { + if usedAccs[acc.AddressBech32] { if len(usedAccs) != len(simState.Accounts) { // Go again if the account is used and there are more to take from i-- @@ -95,7 +81,7 @@ func getGroupPolicies(r *rand.Rand, simState *module.SimulationState) []*group.G continue } - usedAccs[accAddr] = true + usedAccs[acc.AddressBech32] = true any, err := codectypes.NewAnyWithValue(group.NewThresholdDecisionPolicy("10", time.Second, 0)) if err != nil { @@ -103,8 +89,8 @@ func getGroupPolicies(r *rand.Rand, simState *module.SimulationState) []*group.G } groupPolicies = append(groupPolicies, &group.GroupPolicyInfo{ GroupId: uint64(i + 1), - Admin: accAddr, - Address: accAddr, + Admin: acc.AddressBech32, + Address: acc.AddressBech32, Version: 1, DecisionPolicy: any, Metadata: simtypes.RandStringOfLength(r, 10), @@ -115,14 +101,8 @@ func getGroupPolicies(r *rand.Rand, simState *module.SimulationState) []*group.G func getProposals(r *rand.Rand, simState *module.SimulationState, groupPolicies []*group.GroupPolicyInfo) []*group.Proposal { proposals := make([]*group.Proposal, 3) - addr0, err := simState.AddressCodec.BytesToString(simState.Accounts[0].Address) - if err != nil { - panic(err) - } - addr1, err := simState.AddressCodec.BytesToString(simState.Accounts[1].Address) - if err != nil { - panic(err) - } + addr0 := simState.Accounts[0].AddressBech32 + addr1 := simState.Accounts[1].AddressBech32 proposers := []string{addr0, addr1} for i := 0; i < 3; i++ { idx := r.Intn(len(groupPolicies)) @@ -151,14 +131,9 @@ func getProposals(r *rand.Rand, simState *module.SimulationState, groupPolicies VotingPeriodEnd: timeout, } - toAddr, err := simState.AddressCodec.BytesToString(to.Address) - if err != nil { - panic(err) - } - - err = proposal.SetMsgs([]sdk.Msg{&banktypes.MsgSend{ + err := proposal.SetMsgs([]sdk.Msg{&banktypes.MsgSend{ FromAddress: groupPolicyAddress, - ToAddress: toAddr, + ToAddress: to.AddressBech32, Amount: sdk.NewCoins(sdk.NewInt64Coin("test", 10)), }}) if err != nil { @@ -175,10 +150,7 @@ func getVotes(r *rand.Rand, simState *module.SimulationState) []*group.Vote { votes := make([]*group.Vote, 3) for i := 0; i < 3; i++ { - voterAddr, err := simState.AddressCodec.BytesToString(simState.Accounts[i].Address) - if err != nil { - return nil - } + voterAddr := simState.Accounts[i].AddressBech32 votes[i] = &group.Vote{ ProposalId: uint64(i + 1), Voter: voterAddr, @@ -213,11 +185,11 @@ func RandomizedGenState(simState *module.SimulationState) { // groups var groups []*group.GroupInfo - simState.AppParams.GetOrGenerate(GroupInfo, &groups, simState.Rand, func(r *rand.Rand) { groups = getGroups(r, simState.Accounts, simState.AddressCodec) }) + simState.AppParams.GetOrGenerate(GroupInfo, &groups, simState.Rand, func(r *rand.Rand) { groups = getGroups(r, simState.Accounts) }) // group members var members []*group.GroupMember - simState.AppParams.GetOrGenerate(GroupMembers, &members, simState.Rand, func(r *rand.Rand) { members = getGroupMembers(r, simState.Accounts, simState.AddressCodec) }) + simState.AppParams.GetOrGenerate(GroupMembers, &members, simState.Rand, func(r *rand.Rand) { members = getGroupMembers(r, simState.Accounts) }) // group policies var groupPolicies []*group.GroupPolicyInfo diff --git a/x/group/simulation/msg_factory.go b/x/group/simulation/msg_factory.go new file mode 100644 index 000000000000..30b55fc498ce --- /dev/null +++ b/x/group/simulation/msg_factory.go @@ -0,0 +1,487 @@ +package simulation + +import ( + "context" + "slices" + "strconv" + "sync/atomic" + "time" + + "cosmossdk.io/x/group" + "cosmossdk.io/x/group/keeper" + + "github.com/cosmos/cosmos-sdk/simsx" +) + +const unsetGroupID = 100000000000000 + +// SharedState shared state between message invocations +type SharedState struct { + minGroupID atomic.Uint64 +} + +// NewSharedState constructor +func NewSharedState() *SharedState { + r := &SharedState{} + r.setMinGroupID(unsetGroupID) + return r +} + +func (s *SharedState) getMinGroupID() uint64 { + return s.minGroupID.Load() +} + +func (s *SharedState) setMinGroupID(id uint64) { + s.minGroupID.Store(id) +} + +func MsgCreateGroupFactory() simsx.SimMsgFactoryFn[*group.MsgCreateGroup] { + return func(ctx context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter) ([]simsx.SimAccount, *group.MsgCreateGroup) { + admin := testData.AnyAccount(reporter, simsx.WithSpendableBalance()) + members := genGroupMembersX(testData, reporter) + msg := &group.MsgCreateGroup{Admin: admin.AddressBech32, Members: members, Metadata: testData.Rand().StringN(10)} + return []simsx.SimAccount{admin}, msg + } +} + +func MsgCreateGroupPolicyFactory(k keeper.Keeper, s *SharedState) simsx.SimMsgFactoryFn[*group.MsgCreateGroupPolicy] { + return func(ctx context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter) ([]simsx.SimAccount, *group.MsgCreateGroupPolicy) { + groupInfo := randomGroupX(ctx, k, testData, reporter, s) + groupAdmin := testData.GetAccount(reporter, groupInfo.Admin) + if reporter.IsSkipped() { + return nil, nil + } + groupID := groupInfo.Id + + r := testData.Rand() + msg, err := group.NewMsgCreateGroupPolicy( + groupAdmin.AddressBech32, + groupID, + r.StringN(10), + &group.ThresholdDecisionPolicy{ + Threshold: strconv.Itoa(r.IntInRange(1, 10)), + Windows: &group.DecisionPolicyWindows{ + VotingPeriod: time.Second * time.Duration(30*24*60*60), + }, + }, + ) + if err != nil { + reporter.Skip(err.Error()) + return nil, nil + } + return []simsx.SimAccount{groupAdmin}, msg + } +} + +func MsgCreateGroupWithPolicyFactory() simsx.SimMsgFactoryFn[*group.MsgCreateGroupWithPolicy] { + return func(ctx context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter) ([]simsx.SimAccount, *group.MsgCreateGroupWithPolicy) { + admin := testData.AnyAccount(reporter, simsx.WithSpendableBalance()) + members := genGroupMembersX(testData, reporter) + r := testData.Rand() + msg := &group.MsgCreateGroupWithPolicy{ + Admin: admin.AddressBech32, + Members: members, + GroupMetadata: r.StringN(10), + GroupPolicyMetadata: r.StringN(10), + GroupPolicyAsAdmin: r.Float32() < 0.5, + } + decisionPolicy := &group.ThresholdDecisionPolicy{ + Threshold: strconv.Itoa(r.IntInRange(1, 10)), + Windows: &group.DecisionPolicyWindows{ + VotingPeriod: time.Second * time.Duration(30*24*60*60), + }, + } + if err := msg.SetDecisionPolicy(decisionPolicy); err != nil { + reporter.Skip(err.Error()) + return nil, nil + } + return []simsx.SimAccount{admin}, msg + } +} + +func MsgWithdrawProposalFactory(k keeper.Keeper, s *SharedState) simsx.SimMsgFactoryFn[*group.MsgWithdrawProposal] { + return func(ctx context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter) ([]simsx.SimAccount, *group.MsgWithdrawProposal) { + groupInfo, groupPolicy := randomGroupPolicyX(ctx, testData, reporter, k, s) + if reporter.IsSkipped() { + return nil, nil + } + policy, err := groupPolicy.GetDecisionPolicy() + if err != nil { + reporter.Skip(err.Error()) + return nil, nil + } + err = policy.Validate(*groupInfo, group.DefaultConfig()) + if err != nil { + reporter.Skip(err.Error()) + return nil, nil + } + proposalsResult, err := k.ProposalsByGroupPolicy(ctx, + &group.QueryProposalsByGroupPolicyRequest{Address: groupPolicy.Address}, + ) + if err != nil { + reporter.Skip(err.Error()) + return nil, nil + } + + now := simsx.BlockTime(ctx) + proposal := simsx.First(proposalsResult.GetProposals(), func(p *group.Proposal) bool { + return p.Status == group.PROPOSAL_STATUS_SUBMITTED && p.VotingPeriodEnd.After(now) + }) + if proposal == nil { + reporter.Skip("no proposal found") + return nil, nil + } + // select a random proposer + r := testData.Rand() + proposer := testData.GetAccount(reporter, simsx.OneOf(r, (*proposal).Proposers)) + + msg := &group.MsgWithdrawProposal{ + ProposalId: (*proposal).Id, + Address: proposer.AddressBech32, + } + return []simsx.SimAccount{proposer}, msg + } +} + +func MsgVoteFactory(k keeper.Keeper, s *SharedState) simsx.SimMsgFactoryFn[*group.MsgVote] { + return func(ctx context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter) ([]simsx.SimAccount, *group.MsgVote) { + groupInfo, groupPolicy := randomGroupPolicyX(ctx, testData, reporter, k, s) + if reporter.IsSkipped() { + return nil, nil + } + proposalsResult, err := k.ProposalsByGroupPolicy(ctx, + &group.QueryProposalsByGroupPolicyRequest{Address: groupPolicy.Address}, + ) + if err != nil { + reporter.Skip(err.Error()) + return nil, nil + } + + now := simsx.BlockTime(ctx) + proposal := simsx.First(proposalsResult.GetProposals(), func(p *group.Proposal) bool { + return p.Status == group.PROPOSAL_STATUS_SUBMITTED && p.VotingPeriodEnd.After(now) + }) + if proposal == nil { + reporter.Skip("no proposal found") + return nil, nil + } + // select a random member + r := testData.Rand() + res, err := k.GroupMembers(ctx, &group.QueryGroupMembersRequest{GroupId: groupInfo.Id}) + if err != nil { + reporter.Skip(err.Error()) + return nil, nil + } + if len(res.Members) == 0 { + reporter.Skip("group has no members") + return nil, nil + } + voter := testData.GetAccount(reporter, simsx.OneOf(r, res.Members).Member.Address) + vRes, err := k.VotesByProposal(ctx, &group.QueryVotesByProposalRequest{ + ProposalId: (*proposal).Id, + }) + if err != nil { + reporter.Skip(err.Error()) + return nil, nil + } + if slices.ContainsFunc(vRes.Votes, func(v *group.Vote) bool { return v.Voter == voter.AddressBech32 }) { + reporter.Skip("voted already on proposal") + return nil, nil + } + + msg := &group.MsgVote{ + ProposalId: (*proposal).Id, + Voter: voter.AddressBech32, + Option: group.VOTE_OPTION_YES, + Metadata: r.StringN(10), + } + return []simsx.SimAccount{voter}, msg + } +} + +func MsgSubmitProposalFactory(k keeper.Keeper, s *SharedState) simsx.SimMsgFactoryFn[*group.MsgSubmitProposal] { + return func(ctx context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter) ([]simsx.SimAccount, *group.MsgSubmitProposal) { + groupInfo, groupPolicy := randomGroupPolicyX(ctx, testData, reporter, k, s) + if reporter.IsSkipped() { + return nil, nil + } + // Return a no-op if we know the proposal cannot be created + policy, err := groupPolicy.GetDecisionPolicy() + if err != nil { + reporter.Skip(err.Error()) + return nil, nil + } + + if err = policy.Validate(*groupInfo, group.DefaultConfig()); err != nil { + reporter.Skip(err.Error()) + return nil, nil + } + + // Pick a random member from the group + r := testData.Rand() + res, err := k.GroupMembers(ctx, &group.QueryGroupMembersRequest{GroupId: groupInfo.Id}) + if err != nil { + reporter.Skip(err.Error()) + return nil, nil + } + if len(res.Members) == 0 { + reporter.Skip("group has no members") + return nil, nil + } + proposer := testData.GetAccount(reporter, simsx.OneOf(r, res.Members).Member.Address) + + msg := &group.MsgSubmitProposal{ + GroupPolicyAddress: groupPolicy.Address, + Proposers: []string{proposer.AddressBech32}, + Metadata: r.StringN(10), + Title: "Test Proposal", + Summary: "Summary of the proposal", + } + return []simsx.SimAccount{proposer}, msg + } +} + +func MsgExecFactory(k keeper.Keeper, s *SharedState) simsx.SimMsgFactoryFn[*group.MsgExec] { + return func(ctx context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter) ([]simsx.SimAccount, *group.MsgExec) { + groupPolicy, policyAdmin := randomGroupPolicyWithAdmin(ctx, testData, reporter, k, s) + if reporter.IsSkipped() { + return nil, nil + } + proposalsResult, err := k.ProposalsByGroupPolicy(ctx, + &group.QueryProposalsByGroupPolicyRequest{Address: groupPolicy.Address}, + ) + if err != nil { + reporter.Skip(err.Error()) + return nil, nil + } + + proposal := simsx.First(proposalsResult.GetProposals(), func(p *group.Proposal) bool { + return p.Status == group.PROPOSAL_STATUS_ACCEPTED + }) + if proposal == nil { + reporter.Skip("no proposal found") + return nil, nil + } + + msg := &group.MsgExec{ + ProposalId: (*proposal).Id, + Executor: policyAdmin.AddressBech32, + } + return []simsx.SimAccount{policyAdmin}, msg + } +} + +func randomGroupPolicyWithAdmin(ctx context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter, k keeper.Keeper, s *SharedState) (*group.GroupPolicyInfo, simsx.SimAccount) { + for i := 0; i < 5; i++ { + _, groupPolicy := randomGroupPolicyX(ctx, testData, reporter, k, s) + if groupPolicy != nil && testData.HasAccount(groupPolicy.Admin) { + return groupPolicy, testData.GetAccount(reporter, groupPolicy.Admin) + } + } + reporter.Skip("no group policy found with a sims account") + return nil, simsx.SimAccount{} +} + +func MsgUpdateGroupMetadataFactory(k keeper.Keeper, s *SharedState) simsx.SimMsgFactoryFn[*group.MsgUpdateGroupMetadata] { + return func(ctx context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter) ([]simsx.SimAccount, *group.MsgUpdateGroupMetadata) { + groupInfo := randomGroupX(ctx, k, testData, reporter, s) + groupAdmin := testData.GetAccount(reporter, groupInfo.Admin) + if reporter.IsSkipped() { + return nil, nil + } + msg := &group.MsgUpdateGroupMetadata{ + GroupId: groupInfo.Id, + Admin: groupAdmin.AddressBech32, + Metadata: testData.Rand().StringN(10), + } + return []simsx.SimAccount{groupAdmin}, msg + } +} + +func MsgUpdateGroupAdminFactory(k keeper.Keeper, s *SharedState) simsx.SimMsgFactoryFn[*group.MsgUpdateGroupAdmin] { + return func(ctx context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter) ([]simsx.SimAccount, *group.MsgUpdateGroupAdmin) { + groupInfo := randomGroupX(ctx, k, testData, reporter, s) + groupAdmin := testData.GetAccount(reporter, groupInfo.Admin) + if reporter.IsSkipped() { + return nil, nil + } + newAdmin := testData.AnyAccount(reporter, simsx.ExcludeAccounts(groupAdmin)) + msg := &group.MsgUpdateGroupAdmin{ + GroupId: groupInfo.Id, + Admin: groupAdmin.AddressBech32, + NewAdmin: newAdmin.AddressBech32, + } + return []simsx.SimAccount{groupAdmin}, msg + } +} + +func MsgUpdateGroupMembersFactory(k keeper.Keeper, s *SharedState) simsx.SimMsgFactoryFn[*group.MsgUpdateGroupMembers] { + return func(ctx context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter) ([]simsx.SimAccount, *group.MsgUpdateGroupMembers) { + groupInfo := randomGroupX(ctx, k, testData, reporter, s) + groupAdmin := testData.GetAccount(reporter, groupInfo.Admin) + if reporter.IsSkipped() { + return nil, nil + } + res, err := k.GroupMembers(ctx, &group.QueryGroupMembersRequest{GroupId: groupInfo.Id}) + if err != nil { + reporter.Skip("group members not found") + return nil, nil + } + oldMemberAddrs := simsx.Collect(res.Members, func(a *group.GroupMember) string { return a.Member.Address }) + members := genGroupMembersX(testData, reporter, simsx.ExcludeAddresses(oldMemberAddrs...)) + if len(res.Members) != 0 { + // set existing random group member weight to zero to remove from the group + obsoleteMember := simsx.OneOf(testData.Rand(), res.Members) + obsoleteMember.Member.Weight = "0" + members = append(members, group.MemberToMemberRequest(obsoleteMember.Member)) + } + msg := &group.MsgUpdateGroupMembers{ + GroupId: groupInfo.Id, + Admin: groupAdmin.AddressBech32, + MemberUpdates: members, + } + return []simsx.SimAccount{groupAdmin}, msg + } +} + +func MsgUpdateGroupPolicyAdminFactory(k keeper.Keeper, s *SharedState) simsx.SimMsgFactoryFn[*group.MsgUpdateGroupPolicyAdmin] { + return func(ctx context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter) ([]simsx.SimAccount, *group.MsgUpdateGroupPolicyAdmin) { + groupPolicy, policyAdmin := randomGroupPolicyWithAdmin(ctx, testData, reporter, k, s) + if reporter.IsSkipped() { + return nil, nil + } + newAdmin := testData.AnyAccount(reporter, simsx.ExcludeAccounts(policyAdmin)) + msg := &group.MsgUpdateGroupPolicyAdmin{ + Admin: policyAdmin.AddressBech32, + GroupPolicyAddress: groupPolicy.Address, + NewAdmin: newAdmin.AddressBech32, + } + return []simsx.SimAccount{policyAdmin}, msg + } +} + +func MsgUpdateGroupPolicyDecisionPolicyFactory(k keeper.Keeper, s *SharedState) simsx.SimMsgFactoryFn[*group.MsgUpdateGroupPolicyDecisionPolicy] { + return func(ctx context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter) ([]simsx.SimAccount, *group.MsgUpdateGroupPolicyDecisionPolicy) { + groupPolicy, policyAdmin := randomGroupPolicyWithAdmin(ctx, testData, reporter, k, s) + if reporter.IsSkipped() { + return nil, nil + } + r := testData.Rand() + msg, err := group.NewMsgUpdateGroupPolicyDecisionPolicy(policyAdmin.AddressBech32, groupPolicy.Address, &group.ThresholdDecisionPolicy{ + Threshold: strconv.Itoa(r.IntInRange(1, 10)), + Windows: &group.DecisionPolicyWindows{ + VotingPeriod: time.Second * time.Duration(r.IntInRange(100, 1000)), + }, + }) + if err != nil { + reporter.Skip(err.Error()) + return nil, nil + } + return []simsx.SimAccount{policyAdmin}, msg + } +} + +func MsgUpdateGroupPolicyMetadataFactory(k keeper.Keeper, s *SharedState) simsx.SimMsgFactoryFn[*group.MsgUpdateGroupPolicyMetadata] { + return func(ctx context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter) ([]simsx.SimAccount, *group.MsgUpdateGroupPolicyMetadata) { + groupPolicy, policyAdmin := randomGroupPolicyWithAdmin(ctx, testData, reporter, k, s) + if reporter.IsSkipped() { + return nil, nil + } + msg := &group.MsgUpdateGroupPolicyMetadata{ + Admin: policyAdmin.AddressBech32, + GroupPolicyAddress: groupPolicy.Address, + Metadata: testData.Rand().StringN(10), + } + return []simsx.SimAccount{policyAdmin}, msg + } +} + +func MsgLeaveGroupFactory(k keeper.Keeper, s *SharedState) simsx.SimMsgFactoryFn[*group.MsgLeaveGroup] { + return func(ctx context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter) ([]simsx.SimAccount, *group.MsgLeaveGroup) { + groupInfo := randomGroupX(ctx, k, testData, reporter, s) + if reporter.IsSkipped() { + return nil, nil + } + res, err := k.GroupMembers(ctx, &group.QueryGroupMembersRequest{GroupId: groupInfo.Id}) + if err != nil { + reporter.Skip("group members not found") + return nil, nil + } + if len(res.Members) == 0 { + reporter.Skip("group has no members") + return nil, nil + } + anyMember := simsx.OneOf(testData.Rand(), res.Members) + leaver := testData.GetAccount(reporter, anyMember.Member.Address) + msg := &group.MsgLeaveGroup{ + GroupId: groupInfo.Id, + Address: leaver.AddressBech32, + } + return []simsx.SimAccount{leaver}, msg + } +} + +func genGroupMembersX(testData *simsx.ChainDataSource, reporter simsx.SimulationReporter, filters ...simsx.SimAccountFilter) []group.MemberRequest { + r := testData.Rand() + membersCount := r.Intn(5) + 1 + members := make([]group.MemberRequest, membersCount) + uniqueAccountsFilter := simsx.UniqueAccounts() + for i := 0; i < membersCount && !reporter.IsSkipped(); i++ { + m := testData.AnyAccount(reporter, append(filters, uniqueAccountsFilter)...) + members[i] = group.MemberRequest{ + Address: m.AddressBech32, + Weight: strconv.Itoa(r.IntInRange(1, 10)), + Metadata: r.StringN(10), + } + } + return members +} + +func randomGroupX(ctx context.Context, k keeper.Keeper, testdata *simsx.ChainDataSource, reporter simsx.SimulationReporter, s *SharedState) *group.GroupInfo { + r := testdata.Rand() + groupID := k.GetGroupSequence(ctx) + if initialGroupID := s.getMinGroupID(); initialGroupID == unsetGroupID { + s.setMinGroupID(groupID) + } else if initialGroupID < groupID { + groupID = r.Uint64InRange(initialGroupID+1, groupID+1) + } + + // when groupID is 0, it proves that SimulateMsgCreateGroup has never been called. that is, no group exists in the chain + if groupID == 0 { + reporter.Skip("no group exists") + return nil + } + + res, err := k.GroupInfo(ctx, &group.QueryGroupInfoRequest{GroupId: groupID}) + if err != nil { + reporter.Skip(err.Error()) + return nil + } + return res.Info +} + +func randomGroupPolicyX( + ctx context.Context, + testdata *simsx.ChainDataSource, + reporter simsx.SimulationReporter, + k keeper.Keeper, + s *SharedState, +) (*group.GroupInfo, *group.GroupPolicyInfo) { + for i := 0; i < 5; i++ { + groupInfo := randomGroupX(ctx, k, testdata, reporter, s) + if reporter.IsSkipped() { + return nil, nil + } + groupID := groupInfo.Id + result, err := k.GroupPoliciesByGroup(ctx, &group.QueryGroupPoliciesByGroupRequest{GroupId: groupID}) + if err != nil { + reporter.Skip(err.Error()) + return nil, nil + } + if len(result.GroupPolicies) != 0 { + return groupInfo, simsx.OneOf(testdata.Rand(), result.GroupPolicies) + } + } + reporter.Skip("no group policies") + return nil, nil +} diff --git a/x/group/simulation/operations.go b/x/group/simulation/operations.go deleted file mode 100644 index bab0939fddaf..000000000000 --- a/x/group/simulation/operations.go +++ /dev/null @@ -1,1508 +0,0 @@ -package simulation - -import ( - "context" - "fmt" - "math/rand" - "strings" - "sync/atomic" - "time" - - gogoprotoany "github.com/cosmos/gogoproto/types/any" - - "cosmossdk.io/core/address" - "cosmossdk.io/x/group" - "cosmossdk.io/x/group/keeper" - - "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/codec" - cdctypes "github.com/cosmos/cosmos-sdk/codec/types" - simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" - sdk "github.com/cosmos/cosmos-sdk/types" - simtypes "github.com/cosmos/cosmos-sdk/types/simulation" - "github.com/cosmos/cosmos-sdk/x/simulation" -) - -const unsetGroupID = 100000000000000 - -// group message types -var ( - TypeMsgCreateGroup = sdk.MsgTypeURL(&group.MsgCreateGroup{}) - TypeMsgUpdateGroupMembers = sdk.MsgTypeURL(&group.MsgUpdateGroupMembers{}) - TypeMsgUpdateGroupAdmin = sdk.MsgTypeURL(&group.MsgUpdateGroupAdmin{}) - TypeMsgUpdateGroupMetadata = sdk.MsgTypeURL(&group.MsgUpdateGroupMetadata{}) - TypeMsgCreateGroupWithPolicy = sdk.MsgTypeURL(&group.MsgCreateGroupWithPolicy{}) - TypeMsgCreateGroupPolicy = sdk.MsgTypeURL(&group.MsgCreateGroupPolicy{}) - TypeMsgUpdateGroupPolicyAdmin = sdk.MsgTypeURL(&group.MsgUpdateGroupPolicyAdmin{}) - TypeMsgUpdateGroupPolicyDecisionPolicy = sdk.MsgTypeURL(&group.MsgUpdateGroupPolicyDecisionPolicy{}) - TypeMsgUpdateGroupPolicyMetadata = sdk.MsgTypeURL(&group.MsgUpdateGroupPolicyMetadata{}) - TypeMsgSubmitProposal = sdk.MsgTypeURL(&group.MsgSubmitProposal{}) - TypeMsgWithdrawProposal = sdk.MsgTypeURL(&group.MsgWithdrawProposal{}) - TypeMsgVote = sdk.MsgTypeURL(&group.MsgVote{}) - TypeMsgExec = sdk.MsgTypeURL(&group.MsgExec{}) - TypeMsgLeaveGroup = sdk.MsgTypeURL(&group.MsgLeaveGroup{}) -) - -// Simulation operation weights constants -const ( - OpMsgCreateGroup = "op_weight_msg_create_group" - OpMsgUpdateGroupAdmin = "op_weight_msg_update_group_admin" - OpMsgUpdateGroupMetadata = "op_wieght_msg_update_group_metadata" - OpMsgUpdateGroupMembers = "op_weight_msg_update_group_members" - OpMsgCreateGroupPolicy = "op_weight_msg_create_group_account" - OpMsgCreateGroupWithPolicy = "op_weight_msg_create_group_with_policy" - OpMsgUpdateGroupPolicyAdmin = "op_weight_msg_update_group_account_admin" - OpMsgUpdateGroupPolicyDecisionPolicy = "op_weight_msg_update_group_account_decision_policy" - OpMsgUpdateGroupPolicyMetaData = "op_weight_msg_update_group_account_metadata" - OpMsgSubmitProposal = "op_weight_msg_submit_proposal" - OpMsgWithdrawProposal = "op_weight_msg_withdraw_proposal" - OpMsgVote = "op_weight_msg_vote" - OpMsgExec = "ops_weight_msg_exec" - OpMsgLeaveGroup = "ops_weight_msg_leave_group" -) - -// If update group or group policy txn's executed, `SimulateMsgVote` & `SimulateMsgExec` txn's returns `noOp`. -// That's why we have less weight for update group & group-policy txn's. -const ( - WeightMsgCreateGroup = 100 - WeightMsgCreateGroupPolicy = 50 - WeightMsgSubmitProposal = 90 - WeightMsgVote = 90 - WeightMsgExec = 90 - WeightMsgLeaveGroup = 5 - WeightMsgUpdateGroupMetadata = 5 - WeightMsgUpdateGroupAdmin = 5 - WeightMsgUpdateGroupMembers = 5 - WeightMsgUpdateGroupPolicyAdmin = 5 - WeightMsgUpdateGroupPolicyDecisionPolicy = 5 - WeightMsgUpdateGroupPolicyMetadata = 5 - WeightMsgWithdrawProposal = 20 - WeightMsgCreateGroupWithPolicy = 50 -) - -// SharedState shared state between message invocations -type SharedState struct { - minGroupID atomic.Uint64 -} - -// NewSharedState constructor -func NewSharedState() *SharedState { - r := &SharedState{} - r.setMinGroupID(unsetGroupID) - return r -} - -func (s *SharedState) getMinGroupID() uint64 { - return s.minGroupID.Load() -} - -func (s *SharedState) setMinGroupID(id uint64) { - s.minGroupID.Store(id) -} - -// WeightedOperations returns all the operations from the module with their respective weights -func WeightedOperations( - registry cdctypes.InterfaceRegistry, - appParams simtypes.AppParams, cdc codec.JSONCodec, txGen client.TxConfig, - ak group.AccountKeeper, bk group.BankKeeper, k keeper.Keeper, - appCdc gogoprotoany.AnyUnpacker, -) simulation.WeightedOperations { - var ( - weightMsgCreateGroup int - weightMsgUpdateGroupAdmin int - weightMsgUpdateGroupMetadata int - weightMsgUpdateGroupMembers int - weightMsgCreateGroupPolicy int - weightMsgUpdateGroupPolicyAdmin int - weightMsgUpdateGroupPolicyDecisionPolicy int - weightMsgUpdateGroupPolicyMetadata int - weightMsgSubmitProposal int - weightMsgVote int - weightMsgExec int - weightMsgLeaveGroup int - weightMsgWithdrawProposal int - weightMsgCreateGroupWithPolicy int - ) - - appParams.GetOrGenerate(OpMsgCreateGroup, &weightMsgCreateGroup, nil, func(_ *rand.Rand) { - weightMsgCreateGroup = WeightMsgCreateGroup - }) - appParams.GetOrGenerate(OpMsgCreateGroupPolicy, &weightMsgCreateGroupPolicy, nil, func(_ *rand.Rand) { - weightMsgCreateGroupPolicy = WeightMsgCreateGroupPolicy - }) - appParams.GetOrGenerate(OpMsgLeaveGroup, &weightMsgLeaveGroup, nil, func(_ *rand.Rand) { - weightMsgLeaveGroup = WeightMsgLeaveGroup - }) - appParams.GetOrGenerate(OpMsgCreateGroupWithPolicy, &weightMsgCreateGroupWithPolicy, nil, func(_ *rand.Rand) { - weightMsgCreateGroupWithPolicy = WeightMsgCreateGroupWithPolicy - }) - appParams.GetOrGenerate(OpMsgSubmitProposal, &weightMsgSubmitProposal, nil, func(_ *rand.Rand) { - weightMsgSubmitProposal = WeightMsgSubmitProposal - }) - appParams.GetOrGenerate(OpMsgVote, &weightMsgVote, nil, func(_ *rand.Rand) { - weightMsgVote = WeightMsgVote - }) - appParams.GetOrGenerate(OpMsgExec, &weightMsgExec, nil, func(_ *rand.Rand) { - weightMsgExec = WeightMsgExec - }) - appParams.GetOrGenerate(OpMsgUpdateGroupMetadata, &weightMsgUpdateGroupMetadata, nil, func(_ *rand.Rand) { - weightMsgUpdateGroupMetadata = WeightMsgUpdateGroupMetadata - }) - appParams.GetOrGenerate(OpMsgUpdateGroupAdmin, &weightMsgUpdateGroupAdmin, nil, func(_ *rand.Rand) { - weightMsgUpdateGroupAdmin = WeightMsgUpdateGroupAdmin - }) - appParams.GetOrGenerate(OpMsgUpdateGroupMembers, &weightMsgUpdateGroupMembers, nil, func(_ *rand.Rand) { - weightMsgUpdateGroupMembers = WeightMsgUpdateGroupMembers - }) - appParams.GetOrGenerate(OpMsgUpdateGroupPolicyAdmin, &weightMsgUpdateGroupPolicyAdmin, nil, func(_ *rand.Rand) { - weightMsgUpdateGroupPolicyAdmin = WeightMsgUpdateGroupPolicyAdmin - }) - appParams.GetOrGenerate(OpMsgUpdateGroupPolicyDecisionPolicy, &weightMsgUpdateGroupPolicyDecisionPolicy, nil, func(_ *rand.Rand) { - weightMsgUpdateGroupPolicyDecisionPolicy = WeightMsgUpdateGroupPolicyDecisionPolicy - }) - appParams.GetOrGenerate(OpMsgUpdateGroupPolicyMetaData, &weightMsgUpdateGroupPolicyMetadata, nil, func(_ *rand.Rand) { - weightMsgUpdateGroupPolicyMetadata = WeightMsgUpdateGroupPolicyMetadata - }) - appParams.GetOrGenerate(OpMsgWithdrawProposal, &weightMsgWithdrawProposal, nil, func(_ *rand.Rand) { - weightMsgWithdrawProposal = WeightMsgWithdrawProposal - }) - - pCdc := codec.NewProtoCodec(registry) - - state := NewSharedState() - - // create two proposals for weightedOperations - var createProposalOps simulation.WeightedOperations - for i := 0; i < 2; i++ { - createProposalOps = append(createProposalOps, simulation.NewWeightedOperation( - weightMsgSubmitProposal, - SimulateMsgSubmitProposal(pCdc, txGen, ak, bk, k, state), - )) - } - - wPreCreateProposalOps := simulation.WeightedOperations{ - simulation.NewWeightedOperation( - weightMsgCreateGroup, - SimulateMsgCreateGroup(pCdc, txGen, ak, bk), - ), - simulation.NewWeightedOperation( - weightMsgCreateGroupPolicy, - SimulateMsgCreateGroupPolicy(pCdc, txGen, ak, bk, k, state), - ), - simulation.NewWeightedOperation( - weightMsgCreateGroupWithPolicy, - SimulateMsgCreateGroupWithPolicy(pCdc, txGen, ak, bk), - ), - } - - wPostCreateProposalOps := simulation.WeightedOperations{ - simulation.NewWeightedOperation( - WeightMsgWithdrawProposal, - SimulateMsgWithdrawProposal(pCdc, txGen, ak, bk, k, state), - ), - simulation.NewWeightedOperation( - weightMsgVote, - SimulateMsgVote(pCdc, txGen, ak, bk, k, state), - ), - simulation.NewWeightedOperation( - weightMsgExec, - SimulateMsgExec(pCdc, txGen, ak, bk, k, state), - ), - simulation.NewWeightedOperation( - weightMsgUpdateGroupMetadata, - SimulateMsgUpdateGroupMetadata(pCdc, txGen, ak, bk, k, state), - ), - simulation.NewWeightedOperation( - weightMsgUpdateGroupAdmin, - SimulateMsgUpdateGroupAdmin(pCdc, txGen, ak, bk, k, state), - ), - simulation.NewWeightedOperation( - weightMsgUpdateGroupMembers, - SimulateMsgUpdateGroupMembers(pCdc, txGen, ak, bk, k, state), - ), - simulation.NewWeightedOperation( - weightMsgUpdateGroupPolicyAdmin, - SimulateMsgUpdateGroupPolicyAdmin(pCdc, txGen, ak, bk, k, state), - ), - simulation.NewWeightedOperation( - weightMsgUpdateGroupPolicyDecisionPolicy, - SimulateMsgUpdateGroupPolicyDecisionPolicy(pCdc, txGen, ak, bk, k, state), - ), - simulation.NewWeightedOperation( - weightMsgUpdateGroupPolicyMetadata, - SimulateMsgUpdateGroupPolicyMetadata(pCdc, txGen, ak, bk, k, state), - ), - simulation.NewWeightedOperation( - weightMsgLeaveGroup, - SimulateMsgLeaveGroup(pCdc, txGen, k, ak, bk, state), - ), - } - - return append(wPreCreateProposalOps, append(createProposalOps, wPostCreateProposalOps...)...) -} - -// SimulateMsgCreateGroup generates a MsgCreateGroup with random values -func SimulateMsgCreateGroup( - cdc *codec.ProtoCodec, - txGen client.TxConfig, - ak group.AccountKeeper, - bk group.BankKeeper, -) simtypes.Operation { - return func( - r *rand.Rand, app simtypes.AppEntrypoint, ctx sdk.Context, accounts []simtypes.Account, chainID string, - ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { - acc, _ := simtypes.RandomAcc(r, accounts) - account := ak.GetAccount(ctx, acc.Address) - accAddr, err := ak.AddressCodec().BytesToString(acc.Address) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgCreateGroup, "error getting account address"), nil, err - } - - spendableCoins := bk.SpendableCoins(ctx, account.GetAddress()) - fees, err := simtypes.RandomFees(r, spendableCoins) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgCreateGroup, "fee error"), nil, err - } - - members, err := genGroupMembers(r, accounts, ak.AddressCodec()) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgCreateGroup, "error generating group members"), nil, err - } - msg := &group.MsgCreateGroup{Admin: accAddr, Members: members, Metadata: simtypes.RandStringOfLength(r, 10)} - - tx, err := simtestutil.GenSignedMockTx( - r, - txGen, - []sdk.Msg{msg}, - fees, - simtestutil.DefaultGenTxGas, - chainID, - []uint64{account.GetAccountNumber()}, - []uint64{account.GetSequence()}, - acc.PrivKey, - ) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgCreateGroup, "unable to generate mock tx"), nil, err - } - - _, _, err = app.SimDeliver(txGen.TxEncoder(), tx) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, sdk.MsgTypeURL(msg), "unable to deliver tx"), nil, err - } - - return simtypes.NewOperationMsg(msg, true, ""), nil, err - } -} - -// SimulateMsgCreateGroupWithPolicy generates a MsgCreateGroupWithPolicy with random values -func SimulateMsgCreateGroupWithPolicy( - cdc *codec.ProtoCodec, - txGen client.TxConfig, - ak group.AccountKeeper, - bk group.BankKeeper, -) simtypes.Operation { - return func( - r *rand.Rand, app simtypes.AppEntrypoint, ctx sdk.Context, accounts []simtypes.Account, chainID string, - ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { - acc, _ := simtypes.RandomAcc(r, accounts) - account := ak.GetAccount(ctx, acc.Address) - accAddr, err := ak.AddressCodec().BytesToString(acc.Address) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgCreateGroup, "error getting account address"), nil, err - } - - spendableCoins := bk.SpendableCoins(ctx, account.GetAddress()) - fees, err := simtypes.RandomFees(r, spendableCoins) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgCreateGroup, "fee error"), nil, err - } - - members, err := genGroupMembers(r, accounts, ak.AddressCodec()) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgCreateGroup, "error generating group members"), nil, err - } - decisionPolicy := &group.ThresholdDecisionPolicy{ - Threshold: fmt.Sprintf("%d", simtypes.RandIntBetween(r, 1, 10)), - Windows: &group.DecisionPolicyWindows{ - VotingPeriod: time.Second * time.Duration(30*24*60*60), - }, - } - - msg := &group.MsgCreateGroupWithPolicy{ - Admin: accAddr, - Members: members, - GroupMetadata: simtypes.RandStringOfLength(r, 10), - GroupPolicyMetadata: simtypes.RandStringOfLength(r, 10), - GroupPolicyAsAdmin: r.Float32() < 0.5, - } - err = msg.SetDecisionPolicy(decisionPolicy) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, sdk.MsgTypeURL(msg), "unable to set decision policy"), nil, err - } - - tx, err := simtestutil.GenSignedMockTx( - r, - txGen, - []sdk.Msg{msg}, - fees, - simtestutil.DefaultGenTxGas, - chainID, - []uint64{account.GetAccountNumber()}, - []uint64{account.GetSequence()}, - acc.PrivKey, - ) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgCreateGroupWithPolicy, "unable to generate mock tx"), nil, err - } - - _, _, err = app.SimDeliver(txGen.TxEncoder(), tx) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, sdk.MsgTypeURL(msg), "unable to deliver tx"), nil, err - } - - return simtypes.NewOperationMsg(msg, true, ""), nil, nil - } -} - -// SimulateMsgCreateGroupPolicy generates a NewMsgCreateGroupPolicy with random values -func SimulateMsgCreateGroupPolicy( - cdc *codec.ProtoCodec, - txGen client.TxConfig, - ak group.AccountKeeper, - bk group.BankKeeper, - k keeper.Keeper, - s *SharedState, -) simtypes.Operation { - return func( - r *rand.Rand, app simtypes.AppEntrypoint, sdkCtx sdk.Context, accounts []simtypes.Account, chainID string, - ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { - groupInfo, acc, account, err := randomGroup(r, k, ak, sdkCtx, accounts, s) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgCreateGroupPolicy, ""), nil, err - } - if groupInfo == nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgCreateGroupPolicy, ""), nil, nil - } - groupID := groupInfo.Id - - spendableCoins := bk.SpendableCoins(sdkCtx, account.GetAddress()) - fees, err := simtypes.RandomFees(r, spendableCoins) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgCreateGroupPolicy, "fee error"), nil, err - } - - accAddr, err := ak.AddressCodec().BytesToString(acc.Address) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgCreateGroupPolicy, "error generating admin address"), nil, err - } - - msg, err := group.NewMsgCreateGroupPolicy( - accAddr, - groupID, - simtypes.RandStringOfLength(r, 10), - &group.ThresholdDecisionPolicy{ - Threshold: fmt.Sprintf("%d", simtypes.RandIntBetween(r, 1, 10)), - Windows: &group.DecisionPolicyWindows{ - VotingPeriod: time.Second * time.Duration(30*24*60*60), - }, - }, - ) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgCreateGroupPolicy, err.Error()), nil, err - } - - tx, err := simtestutil.GenSignedMockTx( - r, - txGen, - []sdk.Msg{msg}, - fees, - simtestutil.DefaultGenTxGas, - chainID, - []uint64{account.GetAccountNumber()}, - []uint64{account.GetSequence()}, - acc.PrivKey, - ) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgCreateGroupPolicy, "unable to generate mock tx"), nil, err - } - - _, _, err = app.SimDeliver(txGen.TxEncoder(), tx) - if err != nil { - fmt.Printf("ERR DELIVER %v\n", err) - return simtypes.NoOpMsg(group.ModuleName, sdk.MsgTypeURL(msg), "unable to deliver tx"), nil, err - } - - return simtypes.NewOperationMsg(msg, true, ""), nil, err - } -} - -// SimulateMsgSubmitProposal generates a NewMsgSubmitProposal with random values -func SimulateMsgSubmitProposal( - cdc *codec.ProtoCodec, - txGen client.TxConfig, - ak group.AccountKeeper, - bk group.BankKeeper, - k keeper.Keeper, - s *SharedState, -) simtypes.Operation { - return func( - r *rand.Rand, app simtypes.AppEntrypoint, sdkCtx sdk.Context, accounts []simtypes.Account, chainID string, - ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { - g, groupPolicy, _, _, err := randomGroupPolicy(r, k, ak, sdkCtx, accounts, s) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgSubmitProposal, ""), nil, err - } - if g == nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgSubmitProposal, "no group found"), nil, nil - } - if groupPolicy == nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgSubmitProposal, "no group policy found"), nil, nil - } - groupID := g.Id - groupPolicyAddr := groupPolicy.Address - - // Return a no-op if we know the proposal cannot be created - policy, err := groupPolicy.GetDecisionPolicy() - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgSubmitProposal, ""), nil, nil - } - err = policy.Validate(*g, group.DefaultConfig()) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgSubmitProposal, ""), nil, nil - } - - // Pick a random member from the group - acc, account, err := randomMember(sdkCtx, r, k, ak, accounts, groupID) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgSubmitProposal, ""), nil, err - } - if account == nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgSubmitProposal, "no group member found"), nil, nil - } - - spendableCoins := bk.SpendableCoins(sdkCtx, account.GetAddress()) - fees, err := simtypes.RandomFees(r, spendableCoins) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgSubmitProposal, "fee error"), nil, err - } - - accAddr, err := ak.AddressCodec().BytesToString(acc.Address) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgSubmitProposal, "error getting account address"), nil, err - } - - msg := &group.MsgSubmitProposal{ - GroupPolicyAddress: groupPolicyAddr, - Proposers: []string{accAddr}, - Metadata: simtypes.RandStringOfLength(r, 10), - Title: "Test Proposal", - Summary: "Summary of the proposal", - } - - tx, err := simtestutil.GenSignedMockTx( - r, - txGen, - []sdk.Msg{msg}, - fees, - simtestutil.DefaultGenTxGas, - chainID, - []uint64{account.GetAccountNumber()}, - []uint64{account.GetSequence()}, - acc.PrivKey, - ) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgSubmitProposal, "unable to generate mock tx"), nil, err - } - - _, _, err = app.SimDeliver(txGen.TxEncoder(), tx) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, sdk.MsgTypeURL(msg), "unable to deliver tx"), nil, err - } - - return simtypes.NewOperationMsg(msg, true, ""), nil, err - } -} - -// SimulateMsgUpdateGroupAdmin generates a MsgUpdateGroupAdmin with random values -func SimulateMsgUpdateGroupAdmin( - cdc *codec.ProtoCodec, - txGen client.TxConfig, - ak group.AccountKeeper, - bk group.BankKeeper, - k keeper.Keeper, - s *SharedState, -) simtypes.Operation { - return func( - r *rand.Rand, app simtypes.AppEntrypoint, sdkCtx sdk.Context, accounts []simtypes.Account, chainID string, - ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { - groupInfo, acc, account, err := randomGroup(r, k, ak, sdkCtx, accounts, s) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupAdmin, ""), nil, err - } - if groupInfo == nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupAdmin, ""), nil, nil - } - groupID := groupInfo.Id - - spendableCoins := bk.SpendableCoins(sdkCtx, account.GetAddress()) - fees, err := simtypes.RandomFees(r, spendableCoins) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupAdmin, "fee error"), nil, err - } - - if len(accounts) == 1 { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupAdmin, "can't set a new admin with only one account"), nil, nil - } - newAdmin, _ := simtypes.RandomAcc(r, accounts) - // disallow setting current admin as new admin - for acc.PubKey.Equals(newAdmin.PubKey) { - newAdmin, _ = simtypes.RandomAcc(r, accounts) - } - - accAddr, err := ak.AddressCodec().BytesToString(account.GetAddress()) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupAdmin, "error getting admin address"), nil, err - } - newAdminAddr, err := ak.AddressCodec().BytesToString(newAdmin.Address) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupAdmin, "error getting new admin address"), nil, err - } - msg := &group.MsgUpdateGroupAdmin{ - GroupId: groupID, - Admin: accAddr, - NewAdmin: newAdminAddr, - } - - tx, err := simtestutil.GenSignedMockTx( - r, - txGen, - []sdk.Msg{msg}, - fees, - simtestutil.DefaultGenTxGas, - chainID, - []uint64{account.GetAccountNumber()}, - []uint64{account.GetSequence()}, - acc.PrivKey, - ) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupAdmin, "unable to generate mock tx"), nil, err - } - - _, _, err = app.SimDeliver(txGen.TxEncoder(), tx) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, sdk.MsgTypeURL(msg), "unable to deliver tx"), nil, err - } - - return simtypes.NewOperationMsg(msg, true, ""), nil, err - } -} - -// SimulateMsgUpdateGroupMetadata generates a MsgUpdateGroupMetadata with random values -func SimulateMsgUpdateGroupMetadata( - cdc *codec.ProtoCodec, - txGen client.TxConfig, - ak group.AccountKeeper, - bk group.BankKeeper, - k keeper.Keeper, - s *SharedState, -) simtypes.Operation { - return func( - r *rand.Rand, app simtypes.AppEntrypoint, sdkCtx sdk.Context, accounts []simtypes.Account, chainID string, - ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { - groupInfo, acc, account, err := randomGroup(r, k, ak, sdkCtx, accounts, s) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupMetadata, ""), nil, err - } - if groupInfo == nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupMetadata, ""), nil, nil - } - groupID := groupInfo.Id - - spendableCoins := bk.SpendableCoins(sdkCtx, account.GetAddress()) - fees, err := simtypes.RandomFees(r, spendableCoins) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupMetadata, "fee error"), nil, err - } - - adminAddr, err := ak.AddressCodec().BytesToString(account.GetAddress()) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupMetadata, "error getting admin address"), nil, err - } - msg := &group.MsgUpdateGroupMetadata{ - GroupId: groupID, - Admin: adminAddr, - Metadata: simtypes.RandStringOfLength(r, 10), - } - - tx, err := simtestutil.GenSignedMockTx( - r, - txGen, - []sdk.Msg{msg}, - fees, - simtestutil.DefaultGenTxGas, - chainID, - []uint64{account.GetAccountNumber()}, - []uint64{account.GetSequence()}, - acc.PrivKey, - ) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupMetadata, "unable to generate mock tx"), nil, err - } - - _, _, err = app.SimDeliver(txGen.TxEncoder(), tx) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, sdk.MsgTypeURL(msg), "unable to deliver tx"), nil, err - } - - return simtypes.NewOperationMsg(msg, true, ""), nil, err - } -} - -// SimulateMsgUpdateGroupMembers generates a MsgUpdateGroupMembers with random values -func SimulateMsgUpdateGroupMembers( - cdc *codec.ProtoCodec, - txGen client.TxConfig, - ak group.AccountKeeper, - bk group.BankKeeper, - k keeper.Keeper, - s *SharedState, -) simtypes.Operation { - return func( - r *rand.Rand, app simtypes.AppEntrypoint, sdkCtx sdk.Context, accounts []simtypes.Account, chainID string, - ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { - groupInfo, acc, account, err := randomGroup(r, k, ak, sdkCtx, accounts, s) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupMembers, ""), nil, err - } - if groupInfo == nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupMembers, ""), nil, nil - } - groupID := groupInfo.Id - - spendableCoins := bk.SpendableCoins(sdkCtx, account.GetAddress()) - fees, err := simtypes.RandomFees(r, spendableCoins) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupMembers, "fee error"), nil, err - } - - members, err := genGroupMembers(r, accounts, ak.AddressCodec()) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgCreateGroup, "error generating group members"), nil, err - } - ctx := sdk.UnwrapSDKContext(sdkCtx) - res, err := k.GroupMembers(ctx, &group.QueryGroupMembersRequest{GroupId: groupID}) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupMembers, "group members"), nil, err - } - - // set existing random group member weight to zero to remove from the group - existigMembers := res.Members - if len(existigMembers) > 0 { - memberToRemove := existigMembers[r.Intn(len(existigMembers))] - var isDuplicateMember bool - for idx, m := range members { - if m.Address == memberToRemove.Member.Address { - members[idx].Weight = "0" - isDuplicateMember = true - break - } - } - - if !isDuplicateMember { - m := memberToRemove.Member - m.Weight = "0" - members = append(members, group.MemberToMemberRequest(m)) - } - } - - adminAddr, err := ak.AddressCodec().BytesToString(acc.Address) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupMembers, "error getting admin address"), nil, err - } - msg := &group.MsgUpdateGroupMembers{ - GroupId: groupID, - Admin: adminAddr, - MemberUpdates: members, - } - - tx, err := simtestutil.GenSignedMockTx( - r, - txGen, - []sdk.Msg{msg}, - fees, - simtestutil.DefaultGenTxGas, - chainID, - []uint64{account.GetAccountNumber()}, - []uint64{account.GetSequence()}, - acc.PrivKey, - ) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupMembers, "unable to generate mock tx"), nil, err - } - - _, _, err = app.SimDeliver(txGen.TxEncoder(), tx) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, sdk.MsgTypeURL(msg), "unable to deliver tx"), nil, err - } - - return simtypes.NewOperationMsg(msg, true, ""), nil, err - } -} - -// SimulateMsgUpdateGroupPolicyAdmin generates a MsgUpdateGroupPolicyAdmin with random values -func SimulateMsgUpdateGroupPolicyAdmin( - cdc *codec.ProtoCodec, - txGen client.TxConfig, - ak group.AccountKeeper, - bk group.BankKeeper, - k keeper.Keeper, - s *SharedState, -) simtypes.Operation { - return func( - r *rand.Rand, app simtypes.AppEntrypoint, sdkCtx sdk.Context, accounts []simtypes.Account, chainID string, - ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { - _, groupPolicy, acc, account, err := randomGroupPolicy(r, k, ak, sdkCtx, accounts, s) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupPolicyAdmin, ""), nil, err - } - if groupPolicy == nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupPolicyAdmin, "no group policy found"), nil, nil - } - groupPolicyAddr := groupPolicy.Address - - spendableCoins := bk.SpendableCoins(sdkCtx, account.GetAddress()) - fees, err := simtypes.RandomFees(r, spendableCoins) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupPolicyAdmin, "fee error"), nil, err - } - - if len(accounts) == 1 { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupPolicyAdmin, "can't set a new admin with only one account"), nil, nil - } - newAdmin, _ := simtypes.RandomAcc(r, accounts) - // disallow setting current admin as new admin - for acc.PubKey.Equals(newAdmin.PubKey) { - newAdmin, _ = simtypes.RandomAcc(r, accounts) - } - - adminAddr, err := ak.AddressCodec().BytesToString(acc.Address) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupPolicyAdmin, "error getting admin address"), nil, err - } - newAdminAddr, err := ak.AddressCodec().BytesToString(newAdmin.Address) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupPolicyAdmin, "error getting new admin address"), nil, err - } - msg := &group.MsgUpdateGroupPolicyAdmin{ - Admin: adminAddr, - GroupPolicyAddress: groupPolicyAddr, - NewAdmin: newAdminAddr, - } - - tx, err := simtestutil.GenSignedMockTx( - r, - txGen, - []sdk.Msg{msg}, - fees, - simtestutil.DefaultGenTxGas, - chainID, - []uint64{account.GetAccountNumber()}, - []uint64{account.GetSequence()}, - acc.PrivKey, - ) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupPolicyAdmin, "unable to generate mock tx"), nil, err - } - - _, _, err = app.SimDeliver(txGen.TxEncoder(), tx) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, sdk.MsgTypeURL(msg), "unable to deliver tx"), nil, err - } - - return simtypes.NewOperationMsg(msg, true, ""), nil, err - } -} - -// // SimulateMsgUpdateGroupPolicyDecisionPolicy generates a NewMsgUpdateGroupPolicyDecisionPolicy with random values -func SimulateMsgUpdateGroupPolicyDecisionPolicy( - cdc *codec.ProtoCodec, - txGen client.TxConfig, - ak group.AccountKeeper, - bk group.BankKeeper, - k keeper.Keeper, - s *SharedState, -) simtypes.Operation { - return func( - r *rand.Rand, app simtypes.AppEntrypoint, sdkCtx sdk.Context, accounts []simtypes.Account, chainID string, - ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { - _, groupPolicy, acc, account, err := randomGroupPolicy(r, k, ak, sdkCtx, accounts, s) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupPolicyDecisionPolicy, ""), nil, err - } - if groupPolicy == nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupPolicyDecisionPolicy, "no group policy found"), nil, nil - } - groupPolicyAddr := groupPolicy.Address - - spendableCoins := bk.SpendableCoins(sdkCtx, account.GetAddress()) - fees, err := simtypes.RandomFees(r, spendableCoins) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupPolicyDecisionPolicy, "fee error"), nil, err - } - - groupPolicyBech32, err := sdk.AccAddressFromBech32(groupPolicyAddr) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupPolicyDecisionPolicy, fmt.Sprintf("fail to decide bech32 address: %s", err.Error())), nil, nil - } - - accAddr, err := ak.AddressCodec().BytesToString(acc.Address) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupPolicyDecisionPolicy, "error getting admin address"), nil, err - } - groupPolicyStrAddr, err := ak.AddressCodec().BytesToString(groupPolicyBech32) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupPolicyDecisionPolicy, "error group policy admin address"), nil, err - } - - msg, err := group.NewMsgUpdateGroupPolicyDecisionPolicy(accAddr, groupPolicyStrAddr, &group.ThresholdDecisionPolicy{ - Threshold: fmt.Sprintf("%d", simtypes.RandIntBetween(r, 1, 10)), - Windows: &group.DecisionPolicyWindows{ - VotingPeriod: time.Second * time.Duration(simtypes.RandIntBetween(r, 100, 1000)), - }, - }) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupPolicyDecisionPolicy, err.Error()), nil, err - } - - tx, err := simtestutil.GenSignedMockTx( - r, - txGen, - []sdk.Msg{msg}, - fees, - simtestutil.DefaultGenTxGas, - chainID, - []uint64{account.GetAccountNumber()}, - []uint64{account.GetSequence()}, - acc.PrivKey, - ) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupPolicyDecisionPolicy, "unable to generate mock tx"), nil, err - } - - _, _, err = app.SimDeliver(txGen.TxEncoder(), tx) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, sdk.MsgTypeURL(msg), "unable to deliver tx"), nil, err - } - return simtypes.NewOperationMsg(msg, true, ""), nil, err - } -} - -// // SimulateMsgUpdateGroupPolicyMetadata generates a MsgUpdateGroupPolicyMetadata with random values -func SimulateMsgUpdateGroupPolicyMetadata( - cdc *codec.ProtoCodec, - txGen client.TxConfig, - ak group.AccountKeeper, - bk group.BankKeeper, - k keeper.Keeper, - s *SharedState, -) simtypes.Operation { - return func( - r *rand.Rand, app simtypes.AppEntrypoint, sdkCtx sdk.Context, accounts []simtypes.Account, chainID string, - ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { - _, groupPolicy, acc, account, err := randomGroupPolicy(r, k, ak, sdkCtx, accounts, s) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupPolicyMetadata, ""), nil, err - } - if groupPolicy == nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupPolicyMetadata, "no group policy found"), nil, nil - } - groupPolicyAddr := groupPolicy.Address - - spendableCoins := bk.SpendableCoins(sdkCtx, account.GetAddress()) - fees, err := simtypes.RandomFees(r, spendableCoins) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupPolicyMetadata, "fee error"), nil, err - } - - adminAddr, err := ak.AddressCodec().BytesToString(acc.Address) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupPolicyMetadata, "error getting admin address"), nil, err - } - msg := &group.MsgUpdateGroupPolicyMetadata{ - Admin: adminAddr, - GroupPolicyAddress: groupPolicyAddr, - Metadata: simtypes.RandStringOfLength(r, 10), - } - - tx, err := simtestutil.GenSignedMockTx( - r, - txGen, - []sdk.Msg{msg}, - fees, - simtestutil.DefaultGenTxGas, - chainID, - []uint64{account.GetAccountNumber()}, - []uint64{account.GetSequence()}, - acc.PrivKey, - ) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupPolicyMetadata, "unable to generate mock tx"), nil, err - } - - _, _, err = app.SimDeliver(txGen.TxEncoder(), tx) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, sdk.MsgTypeURL(msg), "unable to deliver tx"), nil, err - } - - return simtypes.NewOperationMsg(msg, true, ""), nil, err - } -} - -// SimulateMsgWithdrawProposal generates a MsgWithdrawProposal with random values -func SimulateMsgWithdrawProposal( - cdc *codec.ProtoCodec, - txGen client.TxConfig, - ak group.AccountKeeper, - bk group.BankKeeper, - k keeper.Keeper, - s *SharedState, -) simtypes.Operation { - return func( - r *rand.Rand, app simtypes.AppEntrypoint, sdkCtx sdk.Context, accounts []simtypes.Account, chainID string, - ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { - g, groupPolicy, _, _, err := randomGroupPolicy(r, k, ak, sdkCtx, accounts, s) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgWithdrawProposal, ""), nil, err - } - if g == nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgWithdrawProposal, "no group found"), nil, nil - } - if groupPolicy == nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgWithdrawProposal, "no group policy found"), nil, nil - } - - groupPolicyAddr := groupPolicy.Address - policy, err := groupPolicy.GetDecisionPolicy() - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgWithdrawProposal, err.Error()), nil, nil - } - err = policy.Validate(*g, group.DefaultConfig()) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgWithdrawProposal, err.Error()), nil, nil - } - - proposalsResult, err := k.ProposalsByGroupPolicy(sdkCtx, &group.QueryProposalsByGroupPolicyRequest{Address: groupPolicyAddr}) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgWithdrawProposal, "fail to query group info"), nil, err - } - - proposals := proposalsResult.GetProposals() - if len(proposals) == 0 { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgWithdrawProposal, "no proposals found"), nil, nil - } - - var proposal *group.Proposal - proposalID := -1 - - for _, p := range proposals { - if p.Status == group.PROPOSAL_STATUS_SUBMITTED { - timeout := p.VotingPeriodEnd - proposal = p - proposalID = int(p.Id) - if timeout.Before(sdkCtx.HeaderInfo().Time) || timeout.Equal(sdkCtx.HeaderInfo().Time) { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgWithdrawProposal, "voting period ended: skipping"), nil, nil - } - break - } - } - - // return no-op if no proposal found - if proposalID == -1 { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgWithdrawProposal, "no proposals found"), nil, nil - } - - // select a random proposer - proposers := proposal.Proposers - n := randIntInRange(r, len(proposers)) - proposerIdx, err := findAccount(accounts, proposers[n], ak.AddressCodec()) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgWithdrawProposal, "could not find account"), nil, err - } - proposer := accounts[proposerIdx] - proposerAcc := ak.GetAccount(sdkCtx, proposer.Address) - - spendableCoins := bk.SpendableCoins(sdkCtx, proposer.Address) - fees, err := simtypes.RandomFees(r, spendableCoins) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgWithdrawProposal, "fee error"), nil, err - } - - proposerAddr, err := ak.AddressCodec().BytesToString(proposer.Address) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgWithdrawProposal, "error getting voter address"), nil, err - } - - msg := &group.MsgWithdrawProposal{ - ProposalId: uint64(proposalID), - Address: proposerAddr, - } - - tx, err := simtestutil.GenSignedMockTx( - r, - txGen, - []sdk.Msg{msg}, - fees, - simtestutil.DefaultGenTxGas, - chainID, - []uint64{proposerAcc.GetAccountNumber()}, - []uint64{proposerAcc.GetSequence()}, - proposer.PrivKey, - ) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupPolicyMetadata, "unable to generate mock tx"), nil, err - } - - _, _, err = app.SimDeliver(txGen.TxEncoder(), tx) - if err != nil { - if strings.Contains(err.Error(), "group was modified") || strings.Contains(err.Error(), "group policy was modified") { - return simtypes.NoOpMsg(group.ModuleName, sdk.MsgTypeURL(msg), "no-op:group/group-policy was modified"), nil, nil - } - return simtypes.NoOpMsg(group.ModuleName, sdk.MsgTypeURL(msg), "unable to deliver tx"), nil, err - } - - return simtypes.NewOperationMsg(msg, true, ""), nil, err - } -} - -// SimulateMsgVote generates a MsgVote with random values -func SimulateMsgVote( - cdc *codec.ProtoCodec, - txGen client.TxConfig, - ak group.AccountKeeper, - bk group.BankKeeper, - k keeper.Keeper, - s *SharedState, -) simtypes.Operation { - return func( - r *rand.Rand, app simtypes.AppEntrypoint, sdkCtx sdk.Context, accounts []simtypes.Account, chainID string, - ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { - g, groupPolicy, _, _, err := randomGroupPolicy(r, k, ak, sdkCtx, accounts, s) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgVote, ""), nil, err - } - if g == nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgVote, "no group found"), nil, nil - } - if groupPolicy == nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgVote, "no group policy found"), nil, nil - } - groupPolicyAddr := groupPolicy.Address - - // Pick a random member from the group - acc, account, err := randomMember(sdkCtx, r, k, ak, accounts, g.Id) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgVote, ""), nil, err - } - if account == nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgVote, "no group member found"), nil, nil - } - - spendableCoins := bk.SpendableCoins(sdkCtx, account.GetAddress()) - fees, err := simtypes.RandomFees(r, spendableCoins) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgVote, "fee error"), nil, err - } - - proposalsResult, err := k.ProposalsByGroupPolicy(sdkCtx, &group.QueryProposalsByGroupPolicyRequest{Address: groupPolicyAddr}) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgVote, "fail to query group info"), nil, err - } - proposals := proposalsResult.GetProposals() - if len(proposals) == 0 { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgVote, "no proposals found"), nil, nil - } - - proposalID := -1 - - for _, p := range proposals { - if p.Status == group.PROPOSAL_STATUS_SUBMITTED { - timeout := p.VotingPeriodEnd - proposalID = int(p.Id) - if timeout.Before(sdkCtx.HeaderInfo().Time) || timeout.Equal(sdkCtx.HeaderInfo().Time) { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgVote, "voting period ended: skipping"), nil, nil - } - break - } - } - - // return no-op if no proposal found - if proposalID == -1 { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgVote, "no proposals found"), nil, nil - } - - voterAddr, err := ak.AddressCodec().BytesToString(acc.Address) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgVote, "error getting voter address"), nil, err - } - - // Ensure member hasn't already voted - res, _ := k.VoteByProposalVoter(sdkCtx, &group.QueryVoteByProposalVoterRequest{ - Voter: voterAddr, - ProposalId: uint64(proposalID), - }) - if res != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgVote, "member has already voted"), nil, nil - } - - msg := &group.MsgVote{ - ProposalId: uint64(proposalID), - Voter: voterAddr, - Option: group.VOTE_OPTION_YES, - Metadata: simtypes.RandStringOfLength(r, 10), - } - tx, err := simtestutil.GenSignedMockTx( - r, - txGen, - []sdk.Msg{msg}, - fees, - simtestutil.DefaultGenTxGas, - chainID, - []uint64{account.GetAccountNumber()}, - []uint64{account.GetSequence()}, - acc.PrivKey, - ) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupPolicyMetadata, "unable to generate mock tx"), nil, err - } - - _, _, err = app.SimDeliver(txGen.TxEncoder(), tx) - if err != nil { - if strings.Contains(err.Error(), "group was modified") || strings.Contains(err.Error(), "group policy was modified") { - return simtypes.NoOpMsg(group.ModuleName, sdk.MsgTypeURL(msg), "no-op:group/group-policy was modified"), nil, nil - } - return simtypes.NoOpMsg(group.ModuleName, sdk.MsgTypeURL(msg), "unable to deliver tx"), nil, err - } - - return simtypes.NewOperationMsg(msg, true, ""), nil, err - } -} - -// // SimulateMsgExec generates a MsgExec with random values -func SimulateMsgExec( - cdc *codec.ProtoCodec, - txGen client.TxConfig, - ak group.AccountKeeper, - bk group.BankKeeper, - k keeper.Keeper, - s *SharedState, -) simtypes.Operation { - return func( - r *rand.Rand, app simtypes.AppEntrypoint, sdkCtx sdk.Context, accounts []simtypes.Account, chainID string, - ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { - _, groupPolicy, acc, account, err := randomGroupPolicy(r, k, ak, sdkCtx, accounts, s) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgExec, ""), nil, err - } - if groupPolicy == nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgExec, "no group policy found"), nil, nil - } - groupPolicyAddr := groupPolicy.Address - - spendableCoins := bk.SpendableCoins(sdkCtx, account.GetAddress()) - fees, err := simtypes.RandomFees(r, spendableCoins) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgExec, "fee error"), nil, err - } - - proposalsResult, err := k.ProposalsByGroupPolicy(sdkCtx, &group.QueryProposalsByGroupPolicyRequest{Address: groupPolicyAddr}) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgExec, "fail to query group info"), nil, err - } - proposals := proposalsResult.GetProposals() - if len(proposals) == 0 { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgExec, "no proposals found"), nil, nil - } - - proposalID := -1 - - for _, proposal := range proposals { - if proposal.Status == group.PROPOSAL_STATUS_ACCEPTED { - proposalID = int(proposal.Id) - break - } - } - - // return no-op if no proposal found - if proposalID == -1 { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgExec, "no proposals found"), nil, nil - } - - accAddr, err := ak.AddressCodec().BytesToString(acc.Address) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgExec, "error getting executor address"), nil, err - } - msg := &group.MsgExec{ - ProposalId: uint64(proposalID), - Executor: accAddr, - } - tx, err := simtestutil.GenSignedMockTx( - r, - txGen, - []sdk.Msg{msg}, - fees, - simtestutil.DefaultGenTxGas, - chainID, - []uint64{account.GetAccountNumber()}, - []uint64{account.GetSequence()}, - acc.PrivKey, - ) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupPolicyMetadata, "unable to generate mock tx"), nil, err - } - - _, _, err = app.SimDeliver(txGen.TxEncoder(), tx) - if err != nil { - if strings.Contains(err.Error(), "group was modified") || strings.Contains(err.Error(), "group policy was modified") { - return simtypes.NoOpMsg(group.ModuleName, sdk.MsgTypeURL(msg), "no-op:group/group-policy was modified"), nil, nil - } - return simtypes.NoOpMsg(group.ModuleName, sdk.MsgTypeURL(msg), "unable to deliver tx"), nil, err - } - - return simtypes.NewOperationMsg(msg, true, ""), nil, err - } -} - -// SimulateMsgLeaveGroup generates a MsgLeaveGroup with random values -func SimulateMsgLeaveGroup( - cdc *codec.ProtoCodec, - txGen client.TxConfig, - k keeper.Keeper, - ak group.AccountKeeper, - bk group.BankKeeper, - s *SharedState, -) simtypes.Operation { - return func( - r *rand.Rand, app simtypes.AppEntrypoint, sdkCtx sdk.Context, accounts []simtypes.Account, chainID string, - ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { - groupInfo, policyInfo, _, _, err := randomGroupPolicy(r, k, ak, sdkCtx, accounts, s) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgLeaveGroup, ""), nil, err - } - - if policyInfo == nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgLeaveGroup, "no policy found"), nil, nil - } - - // Pick a random member from the group - acc, account, err := randomMember(sdkCtx, r, k, ak, accounts, groupInfo.Id) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgLeaveGroup, ""), nil, err - } - if account == nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgLeaveGroup, "no group member found"), nil, nil - } - - spendableCoins := bk.SpendableCoins(sdkCtx, acc.Address) - fees, err := simtypes.RandomFees(r, spendableCoins) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgLeaveGroup, "fee error"), nil, err - } - - accAddr, err := ak.AddressCodec().BytesToString(acc.Address) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgLeaveGroup, "error getting account address"), nil, err - } - msg := &group.MsgLeaveGroup{ - Address: accAddr, - GroupId: groupInfo.Id, - } - - tx, err := simtestutil.GenSignedMockTx( - r, - txGen, - []sdk.Msg{msg}, - fees, - simtestutil.DefaultGenTxGas, - chainID, - []uint64{account.GetAccountNumber()}, - []uint64{account.GetSequence()}, - acc.PrivKey, - ) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, TypeMsgLeaveGroup, "unable to generate mock tx"), nil, err - } - - _, _, err = app.SimDeliver(txGen.TxEncoder(), tx) - if err != nil { - return simtypes.NoOpMsg(group.ModuleName, sdk.MsgTypeURL(msg), err.Error()), nil, err - } - - return simtypes.NewOperationMsg(msg, true, ""), nil, err - } -} - -func randomGroup(r *rand.Rand, k keeper.Keeper, ak group.AccountKeeper, - ctx sdk.Context, accounts []simtypes.Account, s *SharedState, -) (groupInfo *group.GroupInfo, acc simtypes.Account, account sdk.AccountI, err error) { - groupID := k.GetGroupSequence(ctx) - - if initialGroupID := s.getMinGroupID(); initialGroupID == unsetGroupID { - s.setMinGroupID(groupID) - } else if initialGroupID < groupID { - groupID = uint64(simtypes.RandIntBetween(r, int(initialGroupID+1), int(groupID+1))) - } - - // when groupID is 0, it proves that SimulateMsgCreateGroup has never been called. that is, no group exists in the chain - if groupID == 0 { - return nil, simtypes.Account{}, nil, nil - } - - res, err := k.GroupInfo(ctx, &group.QueryGroupInfoRequest{GroupId: groupID}) - if err != nil { - return nil, simtypes.Account{}, nil, err - } - - groupInfo = res.Info - groupAdmin := groupInfo.Admin - found := -1 - for i := range accounts { - addr, err := ak.AddressCodec().BytesToString(accounts[i].Address) - if err != nil { - return nil, simtypes.Account{}, nil, err - } - if addr == groupAdmin { - found = i - break - } - } - if found < 0 { - return nil, simtypes.Account{}, nil, nil - } - acc = accounts[found] - account = ak.GetAccount(ctx, acc.Address) - return groupInfo, acc, account, nil -} - -func randomGroupPolicy(r *rand.Rand, k keeper.Keeper, ak group.AccountKeeper, - ctx sdk.Context, accounts []simtypes.Account, s *SharedState, -) (groupInfo *group.GroupInfo, groupPolicyInfo *group.GroupPolicyInfo, acc simtypes.Account, account sdk.AccountI, err error) { - groupInfo, _, _, err = randomGroup(r, k, ak, ctx, accounts, s) - if err != nil { - return nil, nil, simtypes.Account{}, nil, err - } - if groupInfo == nil { - return nil, nil, simtypes.Account{}, nil, nil - } - groupID := groupInfo.Id - - result, err := k.GroupPoliciesByGroup(ctx, &group.QueryGroupPoliciesByGroupRequest{GroupId: groupID}) - if err != nil { - return groupInfo, nil, simtypes.Account{}, nil, err - } - - n := randIntInRange(r, len(result.GroupPolicies)) - if n < 0 { - return groupInfo, nil, simtypes.Account{}, nil, nil - } - groupPolicyInfo = result.GroupPolicies[n] - - idx, err := findAccount(accounts, groupPolicyInfo.Admin, ak.AddressCodec()) - if err != nil { - return groupInfo, nil, simtypes.Account{}, nil, nil - } - - if idx < 0 { - return groupInfo, nil, simtypes.Account{}, nil, nil - } - acc = accounts[idx] - account = ak.GetAccount(ctx, acc.Address) - return groupInfo, groupPolicyInfo, acc, account, nil -} - -func randomMember(ctx context.Context, r *rand.Rand, k keeper.Keeper, ak group.AccountKeeper, - accounts []simtypes.Account, groupID uint64, -) (acc simtypes.Account, account sdk.AccountI, err error) { - res, err := k.GroupMembers(ctx, &group.QueryGroupMembersRequest{ - GroupId: groupID, - }) - if err != nil { - return simtypes.Account{}, nil, err - } - n := randIntInRange(r, len(res.Members)) - if n < 0 { - return simtypes.Account{}, nil, err - } - idx, err := findAccount(accounts, res.Members[n].Member.Address, ak.AddressCodec()) - if err != nil { - return simtypes.Account{}, nil, err - } - if idx < 0 { - return simtypes.Account{}, nil, err - } - acc = accounts[idx] - account = ak.GetAccount(sdk.UnwrapSDKContext(ctx), acc.Address) - return acc, account, nil -} - -func randIntInRange(r *rand.Rand, l int) int { - if l == 0 { - return -1 - } - if l == 1 { - return 0 - } - return simtypes.RandIntBetween(r, 0, l-1) -} - -func findAccount(accounts []simtypes.Account, addr string, addressCodec address.Codec) (idx int, err error) { - idx = -1 - for i := range accounts { - accAddr, err := addressCodec.BytesToString(accounts[i].Address) - if err != nil { - return idx, err - } - if accAddr == addr { - idx = i - break - } - } - return idx, err -} - -func genGroupMembers(r *rand.Rand, accounts []simtypes.Account, addressCodec address.Codec) ([]group.MemberRequest, error) { - if len(accounts) == 1 { - addr, err := addressCodec.BytesToString(accounts[0].Address) - if err != nil { - return nil, err - } - return []group.MemberRequest{ - { - Address: addr, - Weight: fmt.Sprintf("%d", simtypes.RandIntBetween(r, 1, 10)), - Metadata: simtypes.RandStringOfLength(r, 10), - }, - }, nil - } - - max := 5 - if len(accounts) < max { - max = len(accounts) - } - - membersLen := simtypes.RandIntBetween(r, 1, max) - members := make([]group.MemberRequest, membersLen) - - for i := 0; i < membersLen; i++ { - addr, err := addressCodec.BytesToString(accounts[i].Address) - if err != nil { - return nil, err - } - members[i] = group.MemberRequest{ - Address: addr, - Weight: fmt.Sprintf("%d", simtypes.RandIntBetween(r, 1, 10)), - Metadata: simtypes.RandStringOfLength(r, 10), - } - } - - return members, nil -} diff --git a/x/group/simulation/operations_test.go b/x/group/simulation/operations_test.go deleted file mode 100644 index 598e6892b1fa..000000000000 --- a/x/group/simulation/operations_test.go +++ /dev/null @@ -1,759 +0,0 @@ -package simulation_test - -import ( - "math/rand" - "testing" - "time" - - "github.com/cosmos/gogoproto/proto" - "github.com/stretchr/testify/suite" - - "cosmossdk.io/depinject" - "cosmossdk.io/log" - bankkeeper "cosmossdk.io/x/bank/keeper" - "cosmossdk.io/x/bank/testutil" - banktypes "cosmossdk.io/x/bank/types" - "cosmossdk.io/x/group" - groupkeeper "cosmossdk.io/x/group/keeper" - "cosmossdk.io/x/group/simulation" - grouptestutil "cosmossdk.io/x/group/testutil" - - "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/codec" - codectypes "github.com/cosmos/cosmos-sdk/codec/types" - "github.com/cosmos/cosmos-sdk/runtime" - simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" - sdk "github.com/cosmos/cosmos-sdk/types" - simtypes "github.com/cosmos/cosmos-sdk/types/simulation" - authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper" -) - -type SimTestSuite struct { - suite.Suite - - ctx sdk.Context - app *runtime.App - codec codec.Codec - interfaceRegistry codectypes.InterfaceRegistry - txConfig client.TxConfig - accountKeeper authkeeper.AccountKeeper - bankKeeper bankkeeper.Keeper - groupKeeper groupkeeper.Keeper -} - -func (suite *SimTestSuite) SetupTest() { - app, err := simtestutil.Setup( - depinject.Configs( - grouptestutil.AppConfig, - depinject.Supply(log.NewNopLogger()), - ), - &suite.codec, - &suite.interfaceRegistry, - &suite.txConfig, - &suite.accountKeeper, - &suite.bankKeeper, - &suite.groupKeeper, - ) - suite.Require().NoError(err) - - suite.app = app - suite.ctx = app.BaseApp.NewContext(false) -} - -func (suite *SimTestSuite) TestWeightedOperations() { - cdc := suite.codec - appParams := make(simtypes.AppParams) - - weightedOps := simulation.WeightedOperations(suite.interfaceRegistry, appParams, cdc, suite.txConfig, suite.accountKeeper, - suite.bankKeeper, suite.groupKeeper, cdc, - ) - - s := rand.NewSource(2) - r := rand.New(s) - accs := suite.getTestingAccounts(r, 3) - - expected := []struct { - weight int - opMsgRoute string - opMsgName string - }{ - {simulation.WeightMsgCreateGroup, group.ModuleName, simulation.TypeMsgCreateGroup}, - {simulation.WeightMsgCreateGroupPolicy, group.ModuleName, simulation.TypeMsgCreateGroupPolicy}, - {simulation.WeightMsgCreateGroupWithPolicy, group.ModuleName, simulation.TypeMsgCreateGroupWithPolicy}, - {simulation.WeightMsgSubmitProposal, group.ModuleName, simulation.TypeMsgSubmitProposal}, - {simulation.WeightMsgSubmitProposal, group.ModuleName, simulation.TypeMsgSubmitProposal}, - {simulation.WeightMsgWithdrawProposal, group.ModuleName, simulation.TypeMsgWithdrawProposal}, - {simulation.WeightMsgVote, group.ModuleName, simulation.TypeMsgVote}, - {simulation.WeightMsgExec, group.ModuleName, simulation.TypeMsgExec}, - {simulation.WeightMsgUpdateGroupMetadata, group.ModuleName, simulation.TypeMsgUpdateGroupMetadata}, - {simulation.WeightMsgUpdateGroupAdmin, group.ModuleName, simulation.TypeMsgUpdateGroupAdmin}, - {simulation.WeightMsgUpdateGroupMembers, group.ModuleName, simulation.TypeMsgUpdateGroupMembers}, - {simulation.WeightMsgUpdateGroupPolicyAdmin, group.ModuleName, simulation.TypeMsgUpdateGroupPolicyAdmin}, - {simulation.WeightMsgUpdateGroupPolicyDecisionPolicy, group.ModuleName, simulation.TypeMsgUpdateGroupPolicyDecisionPolicy}, - {simulation.WeightMsgUpdateGroupPolicyMetadata, group.ModuleName, simulation.TypeMsgUpdateGroupPolicyMetadata}, - {simulation.WeightMsgLeaveGroup, group.ModuleName, simulation.TypeMsgLeaveGroup}, - } - - for i, w := range weightedOps { - operationMsg, _, err := w.Op()(r, suite.app.BaseApp, suite.ctx, accs, "") - suite.Require().NoError(err) - - // the following checks are very much dependent from the ordering of the output given - // by WeightedOperations. if the ordering in WeightedOperations changes some tests - // will fail - suite.Require().Equal(expected[i].weight, w.Weight(), "weight should be the same") - suite.Require().Equal(expected[i].opMsgRoute, operationMsg.Route, "route should be the same") - suite.Require().Equal(expected[i].opMsgName, operationMsg.Name, "operation Msg name should be the same") - } -} - -func (suite *SimTestSuite) getTestingAccounts(r *rand.Rand, n int) []simtypes.Account { - accounts := simtypes.RandomAccounts(r, n) - - initAmt := sdk.TokensFromConsensusPower(200, sdk.DefaultPowerReduction) - initCoins := sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, initAmt)) - - // add coins to the accounts - for _, account := range accounts { - acc := suite.accountKeeper.NewAccountWithAddress(suite.ctx, account.Address) - suite.accountKeeper.SetAccount(suite.ctx, acc) - suite.Require().NoError(testutil.FundAccount(suite.ctx, suite.bankKeeper, account.Address, initCoins)) - } - - return accounts -} - -func (suite *SimTestSuite) TestSimulateCreateGroup() { - // setup 1 account - s := rand.NewSource(1) - r := rand.New(s) - accounts := suite.getTestingAccounts(r, 1) - - acc := accounts[0] - accAddr, err := suite.accountKeeper.AddressCodec().BytesToString(acc.Address) - suite.Require().NoError(err) - - // execute operation - op := simulation.SimulateMsgCreateGroup(codec.NewProtoCodec(suite.interfaceRegistry), suite.txConfig, suite.accountKeeper, suite.bankKeeper) - operationMsg, futureOperations, err := op(r, suite.app.BaseApp, suite.ctx, accounts, "") - suite.Require().NoError(err) - - var msg group.MsgCreateGroup - err = proto.Unmarshal(operationMsg.Msg, &msg) - suite.Require().NoError(err) - suite.Require().True(operationMsg.OK) - suite.Require().Equal(accAddr, msg.Admin) - suite.Require().Len(futureOperations, 0) -} - -func (suite *SimTestSuite) TestSimulateCreateGroupWithPolicy() { - // setup 1 account - s := rand.NewSource(1) - r := rand.New(s) - accounts := suite.getTestingAccounts(r, 1) - - acc := accounts[0] - accAddr, err := suite.accountKeeper.AddressCodec().BytesToString(acc.Address) - suite.Require().NoError(err) - - // execute operation - op := simulation.SimulateMsgCreateGroupWithPolicy(codec.NewProtoCodec(suite.interfaceRegistry), suite.txConfig, suite.accountKeeper, suite.bankKeeper) - operationMsg, futureOperations, err := op(r, suite.app.BaseApp, suite.ctx, accounts, "") - suite.Require().NoError(err) - - var msg group.MsgCreateGroupWithPolicy - err = proto.Unmarshal(operationMsg.Msg, &msg) - suite.Require().NoError(err) - suite.Require().True(operationMsg.OK) - suite.Require().Equal(accAddr, msg.Admin) - suite.Require().Len(futureOperations, 0) -} - -func (suite *SimTestSuite) TestSimulateCreateGroupPolicy() { - // setup 1 account - s := rand.NewSource(1) - r := rand.New(s) - accounts := suite.getTestingAccounts(r, 1) - acc := accounts[0] - accAddr, err := suite.accountKeeper.AddressCodec().BytesToString(acc.Address) - suite.Require().NoError(err) - - // setup a group - _, err = suite.groupKeeper.CreateGroup(suite.ctx, - &group.MsgCreateGroup{ - Admin: accAddr, - Members: []group.MemberRequest{ - { - Address: accAddr, - Weight: "1", - }, - }, - }, - ) - suite.Require().NoError(err) - - // execute operation - op := simulation.SimulateMsgCreateGroupPolicy(codec.NewProtoCodec(suite.interfaceRegistry), suite.txConfig, suite.accountKeeper, suite.bankKeeper, suite.groupKeeper, simulation.NewSharedState()) - operationMsg, futureOperations, err := op(r, suite.app.BaseApp, suite.ctx, accounts, "") - suite.Require().NoError(err) - - var msg group.MsgCreateGroupPolicy - err = proto.Unmarshal(operationMsg.Msg, &msg) - suite.Require().NoError(err) - suite.Require().True(operationMsg.OK) - suite.Require().Equal(accAddr, msg.Admin) - suite.Require().Len(futureOperations, 0) -} - -func (suite *SimTestSuite) TestSimulateSubmitProposal() { - // setup 1 account - s := rand.NewSource(2) - r := rand.New(s) - accounts := suite.getTestingAccounts(r, 1) - acc := accounts[0] - accAddr, err := suite.accountKeeper.AddressCodec().BytesToString(acc.Address) - suite.Require().NoError(err) - - // setup a group - ctx := suite.ctx - groupRes, err := suite.groupKeeper.CreateGroup(ctx, - &group.MsgCreateGroup{ - Admin: accAddr, - Members: []group.MemberRequest{ - { - Address: accAddr, - Weight: "1", - }, - }, - }, - ) - suite.Require().NoError(err) - - // setup a group account - accountReq := &group.MsgCreateGroupPolicy{ - Admin: accAddr, - GroupId: groupRes.GroupId, - } - err = accountReq.SetDecisionPolicy(group.NewThresholdDecisionPolicy("1", time.Hour, 0)) - suite.Require().NoError(err) - groupPolicyRes, err := suite.groupKeeper.CreateGroupPolicy(ctx, accountReq) - suite.Require().NoError(err) - - // execute operation - op := simulation.SimulateMsgSubmitProposal(codec.NewProtoCodec(suite.interfaceRegistry), suite.txConfig, suite.accountKeeper, suite.bankKeeper, suite.groupKeeper, simulation.NewSharedState()) - operationMsg, futureOperations, err := op(r, suite.app.BaseApp, suite.ctx, accounts, "") - suite.Require().NoError(err) - - var msg group.MsgSubmitProposal - err = proto.Unmarshal(operationMsg.Msg, &msg) - suite.Require().NoError(err) - suite.Require().True(operationMsg.OK) - suite.Require().Equal(groupPolicyRes.Address, msg.GroupPolicyAddress) - suite.Require().Len(futureOperations, 0) -} - -func (suite *SimTestSuite) TestWithdrawProposal() { - // setup 1 account - s := rand.NewSource(1) - r := rand.New(s) - accounts := suite.getTestingAccounts(r, 3) - acc := accounts[0] - accAddr, err := suite.accountKeeper.AddressCodec().BytesToString(acc.Address) - suite.Require().NoError(err) - - // setup a group - ctx := suite.ctx - addr := accAddr - groupRes, err := suite.groupKeeper.CreateGroup(ctx, - &group.MsgCreateGroup{ - Admin: addr, - Members: []group.MemberRequest{ - { - Address: addr, - Weight: "1", - }, - }, - }, - ) - suite.Require().NoError(err) - - // setup a group account - accountReq := &group.MsgCreateGroupPolicy{ - Admin: addr, - GroupId: groupRes.GroupId, - } - err = accountReq.SetDecisionPolicy(group.NewThresholdDecisionPolicy("1", time.Hour, 0)) - suite.Require().NoError(err) - groupPolicyRes, err := suite.groupKeeper.CreateGroupPolicy(ctx, accountReq) - suite.Require().NoError(err) - - // setup a proposal - proposalReq, err := group.NewMsgSubmitProposal(groupPolicyRes.Address, []string{addr}, []sdk.Msg{ - &banktypes.MsgSend{ - FromAddress: groupPolicyRes.Address, - ToAddress: addr, - Amount: sdk.Coins{sdk.NewInt64Coin("token", 100)}, - }, - }, "", 0, "MsgSend", "this is a test proposal") - suite.Require().NoError(err) - _, err = suite.groupKeeper.SubmitProposal(ctx, proposalReq) - suite.Require().NoError(err) - - // execute operation - op := simulation.SimulateMsgWithdrawProposal(codec.NewProtoCodec(suite.interfaceRegistry), suite.txConfig, suite.accountKeeper, suite.bankKeeper, suite.groupKeeper, simulation.NewSharedState()) - operationMsg, futureOperations, err := op(r, suite.app.BaseApp, suite.ctx, accounts, "") - suite.Require().NoError(err) - - var msg group.MsgWithdrawProposal - err = proto.Unmarshal(operationMsg.Msg, &msg) - suite.Require().NoError(err) - suite.Require().True(operationMsg.OK) - suite.Require().Equal(addr, msg.Address) - suite.Require().Len(futureOperations, 0) -} - -func (suite *SimTestSuite) TestSimulateVote() { - // setup 1 account - s := rand.NewSource(1) - r := rand.New(s) - accounts := suite.getTestingAccounts(r, 1) - acc := accounts[0] - accAddr, err := suite.accountKeeper.AddressCodec().BytesToString(acc.Address) - suite.Require().NoError(err) - - // setup a group - ctx := suite.ctx - addr := accAddr - groupRes, err := suite.groupKeeper.CreateGroup(ctx, - &group.MsgCreateGroup{ - Admin: addr, - Members: []group.MemberRequest{ - { - Address: addr, - Weight: "1", - }, - }, - }, - ) - suite.Require().NoError(err) - - // setup a group account - accountReq := &group.MsgCreateGroupPolicy{ - Admin: addr, - GroupId: groupRes.GroupId, - Metadata: "", - } - err = accountReq.SetDecisionPolicy(group.NewThresholdDecisionPolicy("1", time.Hour, 0)) - suite.Require().NoError(err) - groupPolicyRes, err := suite.groupKeeper.CreateGroupPolicy(ctx, accountReq) - suite.Require().NoError(err) - - // setup a proposal - proposalReq, err := group.NewMsgSubmitProposal(groupPolicyRes.Address, []string{addr}, []sdk.Msg{ - &banktypes.MsgSend{ - FromAddress: groupPolicyRes.Address, - ToAddress: addr, - Amount: sdk.Coins{sdk.NewInt64Coin("token", 100)}, - }, - }, "", 0, "MsgSend", "this is a test proposal") - suite.Require().NoError(err) - _, err = suite.groupKeeper.SubmitProposal(ctx, proposalReq) - suite.Require().NoError(err) - - // execute operation - op := simulation.SimulateMsgVote(codec.NewProtoCodec(suite.interfaceRegistry), suite.txConfig, suite.accountKeeper, suite.bankKeeper, suite.groupKeeper, simulation.NewSharedState()) - operationMsg, futureOperations, err := op(r, suite.app.BaseApp, suite.ctx, accounts, "") - suite.Require().NoError(err) - - var msg group.MsgVote - err = proto.Unmarshal(operationMsg.Msg, &msg) - suite.Require().NoError(err) - suite.Require().True(operationMsg.OK) - suite.Require().Equal(addr, msg.Voter) - suite.Require().Len(futureOperations, 0) -} - -func (suite *SimTestSuite) TestSimulateExec() { - // setup 1 account - s := rand.NewSource(1) - r := rand.New(s) - accounts := suite.getTestingAccounts(r, 1) - acc := accounts[0] - accAddr, err := suite.accountKeeper.AddressCodec().BytesToString(acc.Address) - suite.Require().NoError(err) - - // setup a group - ctx := suite.ctx - addr := accAddr - groupRes, err := suite.groupKeeper.CreateGroup(ctx, - &group.MsgCreateGroup{ - Admin: addr, - Members: []group.MemberRequest{ - { - Address: addr, - Weight: "1", - }, - }, - }, - ) - suite.Require().NoError(err) - - // setup a group account - accountReq := &group.MsgCreateGroupPolicy{ - Admin: addr, - GroupId: groupRes.GroupId, - } - err = accountReq.SetDecisionPolicy(group.NewThresholdDecisionPolicy("1", time.Hour, 0)) - suite.Require().NoError(err) - groupPolicyRes, err := suite.groupKeeper.CreateGroupPolicy(ctx, accountReq) - suite.Require().NoError(err) - - // setup a proposal - proposalReq, err := group.NewMsgSubmitProposal(groupPolicyRes.Address, []string{addr}, []sdk.Msg{ - &banktypes.MsgSend{ - FromAddress: groupPolicyRes.Address, - ToAddress: addr, - Amount: sdk.Coins{sdk.NewInt64Coin("token", 100)}, - }, - }, "", 0, "MsgSend", "this is a test proposal") - suite.Require().NoError(err) - proposalRes, err := suite.groupKeeper.SubmitProposal(ctx, proposalReq) - suite.Require().NoError(err) - - // vote - _, err = suite.groupKeeper.Vote(ctx, &group.MsgVote{ - ProposalId: proposalRes.ProposalId, - Voter: addr, - Option: group.VOTE_OPTION_YES, - Exec: 1, - }) - suite.Require().NoError(err) - - // execute operation - op := simulation.SimulateMsgExec(codec.NewProtoCodec(suite.interfaceRegistry), suite.txConfig, suite.accountKeeper, suite.bankKeeper, suite.groupKeeper, simulation.NewSharedState()) - operationMsg, futureOperations, err := op(r, suite.app.BaseApp, suite.ctx, accounts, "") - suite.Require().NoError(err) - - var msg group.MsgExec - err = proto.Unmarshal(operationMsg.Msg, &msg) - suite.Require().NoError(err) - suite.Require().True(operationMsg.OK) - suite.Require().Equal(addr, msg.Executor) - suite.Require().Len(futureOperations, 0) -} - -func (suite *SimTestSuite) TestSimulateUpdateGroupAdmin() { - // setup 1 account - s := rand.NewSource(1) - r := rand.New(s) - accounts := suite.getTestingAccounts(r, 2) - acc := accounts[0] - accAddr, err := suite.accountKeeper.AddressCodec().BytesToString(acc.Address) - suite.Require().NoError(err) - - // setup a group - _, err = suite.groupKeeper.CreateGroup(suite.ctx, - &group.MsgCreateGroup{ - Admin: accAddr, - Members: []group.MemberRequest{ - { - Address: accAddr, - Weight: "1", - }, - }, - }, - ) - suite.Require().NoError(err) - - // execute operation - op := simulation.SimulateMsgUpdateGroupAdmin(codec.NewProtoCodec(suite.interfaceRegistry), suite.txConfig, suite.accountKeeper, suite.bankKeeper, suite.groupKeeper, simulation.NewSharedState()) - operationMsg, futureOperations, err := op(r, suite.app.BaseApp, suite.ctx, accounts, "") - suite.Require().NoError(err) - - var msg group.MsgUpdateGroupAdmin - err = proto.Unmarshal(operationMsg.Msg, &msg) - suite.Require().NoError(err) - suite.Require().True(operationMsg.OK) - suite.Require().Equal(accAddr, msg.Admin) - suite.Require().Len(futureOperations, 0) -} - -func (suite *SimTestSuite) TestSimulateUpdateGroupMetadata() { - // setup 1 account - s := rand.NewSource(1) - r := rand.New(s) - accounts := suite.getTestingAccounts(r, 2) - acc := accounts[0] - accAddr, err := suite.accountKeeper.AddressCodec().BytesToString(acc.Address) - suite.Require().NoError(err) - - // setup a group - _, err = suite.groupKeeper.CreateGroup(suite.ctx, - &group.MsgCreateGroup{ - Admin: accAddr, - Members: []group.MemberRequest{ - { - Address: accAddr, - Weight: "1", - }, - }, - }, - ) - suite.Require().NoError(err) - - // execute operation - op := simulation.SimulateMsgUpdateGroupMetadata(codec.NewProtoCodec(suite.interfaceRegistry), suite.txConfig, suite.accountKeeper, suite.bankKeeper, suite.groupKeeper, simulation.NewSharedState()) - operationMsg, futureOperations, err := op(r, suite.app.BaseApp, suite.ctx, accounts, "") - suite.Require().NoError(err) - - var msg group.MsgUpdateGroupMetadata - err = proto.Unmarshal(operationMsg.Msg, &msg) - suite.Require().NoError(err) - suite.Require().True(operationMsg.OK) - suite.Require().Equal(accAddr, msg.Admin) - suite.Require().Len(futureOperations, 0) -} - -func (suite *SimTestSuite) TestSimulateUpdateGroupMembers() { - // setup 1 account - s := rand.NewSource(1) - r := rand.New(s) - accounts := suite.getTestingAccounts(r, 2) - acc := accounts[0] - accAddr, err := suite.accountKeeper.AddressCodec().BytesToString(acc.Address) - suite.Require().NoError(err) - - // setup a group - _, err = suite.groupKeeper.CreateGroup(suite.ctx, - &group.MsgCreateGroup{ - Admin: accAddr, - Members: []group.MemberRequest{ - { - Address: accAddr, - Weight: "1", - }, - }, - }, - ) - suite.Require().NoError(err) - - // execute operation - op := simulation.SimulateMsgUpdateGroupMembers(codec.NewProtoCodec(suite.interfaceRegistry), suite.txConfig, suite.accountKeeper, suite.bankKeeper, suite.groupKeeper, simulation.NewSharedState()) - operationMsg, futureOperations, err := op(r, suite.app.BaseApp, suite.ctx, accounts, "") - suite.Require().NoError(err) - - var msg group.MsgUpdateGroupMembers - err = proto.Unmarshal(operationMsg.Msg, &msg) - suite.Require().NoError(err) - suite.Require().True(operationMsg.OK) - suite.Require().Equal(accAddr, msg.Admin) - suite.Require().Len(futureOperations, 0) -} - -func (suite *SimTestSuite) TestSimulateUpdateGroupPolicyAdmin() { - // setup 1 account - s := rand.NewSource(1) - r := rand.New(s) - accounts := suite.getTestingAccounts(r, 2) - acc := accounts[0] - accAddr, err := suite.accountKeeper.AddressCodec().BytesToString(acc.Address) - suite.Require().NoError(err) - - // setup a group - ctx := suite.ctx - groupRes, err := suite.groupKeeper.CreateGroup(ctx, - &group.MsgCreateGroup{ - Admin: accAddr, - Members: []group.MemberRequest{ - { - Address: accAddr, - Weight: "1", - }, - }, - }, - ) - suite.Require().NoError(err) - - // setup a group account - accountReq := &group.MsgCreateGroupPolicy{ - Admin: accAddr, - GroupId: groupRes.GroupId, - } - err = accountReq.SetDecisionPolicy(group.NewThresholdDecisionPolicy("1", time.Hour, 0)) - suite.Require().NoError(err) - groupPolicyRes, err := suite.groupKeeper.CreateGroupPolicy(ctx, accountReq) - suite.Require().NoError(err) - - // execute operation - op := simulation.SimulateMsgUpdateGroupPolicyAdmin(codec.NewProtoCodec(suite.interfaceRegistry), suite.txConfig, suite.accountKeeper, suite.bankKeeper, suite.groupKeeper, simulation.NewSharedState()) - operationMsg, futureOperations, err := op(r, suite.app.BaseApp, suite.ctx, accounts, "") - suite.Require().NoError(err) - - var msg group.MsgUpdateGroupPolicyAdmin - err = proto.Unmarshal(operationMsg.Msg, &msg) - suite.Require().NoError(err) - suite.Require().True(operationMsg.OK) - suite.Require().Equal(groupPolicyRes.Address, msg.GroupPolicyAddress) - suite.Require().Len(futureOperations, 0) -} - -func (suite *SimTestSuite) TestSimulateUpdateGroupPolicyDecisionPolicy() { - // setup 1 account - s := rand.NewSource(1) - r := rand.New(s) - accounts := suite.getTestingAccounts(r, 2) - acc := accounts[0] - accAddr, err := suite.accountKeeper.AddressCodec().BytesToString(acc.Address) - suite.Require().NoError(err) - - // setup a group - ctx := suite.ctx - groupRes, err := suite.groupKeeper.CreateGroup(ctx, - &group.MsgCreateGroup{ - Admin: accAddr, - Members: []group.MemberRequest{ - { - Address: accAddr, - Weight: "1", - }, - }, - }, - ) - suite.Require().NoError(err) - - // setup a group account - accountReq := &group.MsgCreateGroupPolicy{ - Admin: accAddr, - GroupId: groupRes.GroupId, - } - err = accountReq.SetDecisionPolicy(group.NewThresholdDecisionPolicy("1", time.Hour, 0)) - suite.Require().NoError(err) - groupPolicyRes, err := suite.groupKeeper.CreateGroupPolicy(ctx, accountReq) - suite.Require().NoError(err) - - // execute operation - op := simulation.SimulateMsgUpdateGroupPolicyDecisionPolicy(codec.NewProtoCodec(suite.interfaceRegistry), suite.txConfig, suite.accountKeeper, suite.bankKeeper, suite.groupKeeper, simulation.NewSharedState()) - operationMsg, futureOperations, err := op(r, suite.app.BaseApp, suite.ctx, accounts, "") - suite.Require().NoError(err) - - var msg group.MsgUpdateGroupPolicyDecisionPolicy - err = proto.Unmarshal(operationMsg.Msg, &msg) - suite.Require().NoError(err) - suite.Require().True(operationMsg.OK) - suite.Require().Equal(groupPolicyRes.Address, msg.GroupPolicyAddress) - suite.Require().Len(futureOperations, 0) -} - -func (suite *SimTestSuite) TestSimulateUpdateGroupPolicyMetadata() { - // setup 1 account - s := rand.NewSource(1) - r := rand.New(s) - accounts := suite.getTestingAccounts(r, 2) - acc := accounts[0] - accAddr, err := suite.accountKeeper.AddressCodec().BytesToString(acc.Address) - suite.Require().NoError(err) - - // setup a group - ctx := suite.ctx - groupRes, err := suite.groupKeeper.CreateGroup(ctx, - &group.MsgCreateGroup{ - Admin: accAddr, - Members: []group.MemberRequest{ - { - Address: accAddr, - Weight: "1", - }, - }, - }, - ) - suite.Require().NoError(err) - - // setup a group account - accountReq := &group.MsgCreateGroupPolicy{ - Admin: accAddr, - GroupId: groupRes.GroupId, - } - err = accountReq.SetDecisionPolicy(group.NewThresholdDecisionPolicy("1", time.Hour, 0)) - suite.Require().NoError(err) - groupPolicyRes, err := suite.groupKeeper.CreateGroupPolicy(ctx, accountReq) - suite.Require().NoError(err) - - // execute operation - op := simulation.SimulateMsgUpdateGroupPolicyMetadata(codec.NewProtoCodec(suite.interfaceRegistry), suite.txConfig, suite.accountKeeper, suite.bankKeeper, suite.groupKeeper, simulation.NewSharedState()) - operationMsg, futureOperations, err := op(r, suite.app.BaseApp, suite.ctx, accounts, "") - suite.Require().NoError(err) - - var msg group.MsgUpdateGroupPolicyMetadata - err = proto.Unmarshal(operationMsg.Msg, &msg) - suite.Require().NoError(err) - suite.Require().True(operationMsg.OK) - suite.Require().Equal(groupPolicyRes.Address, msg.GroupPolicyAddress) - suite.Require().Len(futureOperations, 0) -} - -func (suite *SimTestSuite) TestSimulateLeaveGroup() { - s := rand.NewSource(1) - r := rand.New(s) - require := suite.Require() - - // setup 4 account - accounts := suite.getTestingAccounts(r, 4) - admin := accounts[0] - adminAddr, err := suite.accountKeeper.AddressCodec().BytesToString(admin.Address) - suite.Require().NoError(err) - member1, err := suite.accountKeeper.AddressCodec().BytesToString(accounts[1].Address) - suite.Require().NoError(err) - member2, err := suite.accountKeeper.AddressCodec().BytesToString(accounts[2].Address) - suite.Require().NoError(err) - member3, err := suite.accountKeeper.AddressCodec().BytesToString(accounts[3].Address) - suite.Require().NoError(err) - - // setup a group - ctx := suite.ctx - groupRes, err := suite.groupKeeper.CreateGroup(ctx, - &group.MsgCreateGroup{ - Admin: adminAddr, - Members: []group.MemberRequest{ - { - Address: member1, - Weight: "1", - }, - { - Address: member2, - Weight: "2", - }, - { - Address: member3, - Weight: "1", - }, - }, - }, - ) - require.NoError(err) - - // setup a group account - accountReq := &group.MsgCreateGroupPolicy{ - Admin: adminAddr, - GroupId: groupRes.GroupId, - Metadata: "", - } - require.NoError(accountReq.SetDecisionPolicy(group.NewThresholdDecisionPolicy("3", time.Hour, time.Hour))) - _, err = suite.groupKeeper.CreateGroupPolicy(ctx, accountReq) - require.NoError(err) - - // execute operation - op := simulation.SimulateMsgLeaveGroup(codec.NewProtoCodec(suite.interfaceRegistry), suite.txConfig, suite.groupKeeper, suite.accountKeeper, suite.bankKeeper, simulation.NewSharedState()) - operationMsg, futureOperations, err := op(r, suite.app.BaseApp, suite.ctx, accounts, "") - suite.Require().NoError(err) - - var msg group.MsgLeaveGroup - err = proto.Unmarshal(operationMsg.Msg, &msg) - suite.Require().NoError(err) - suite.Require().True(operationMsg.OK) - suite.Require().Equal(groupRes.GroupId, msg.GroupId) - suite.Require().Len(futureOperations, 0) -} - -func TestSimTestSuite(t *testing.T) { - suite.Run(t, new(SimTestSuite)) -} diff --git a/x/mint/CHANGELOG.md b/x/mint/CHANGELOG.md index 285fab6b5c3b..749a0680d1e2 100644 --- a/x/mint/CHANGELOG.md +++ b/x/mint/CHANGELOG.md @@ -32,9 +32,13 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### Improvements +### Bug Fixes + ### API Breaking Changes * [#20363](https://github.com/cosmos/cosmos-sdk/pull/20363) Deprecated InflationCalculationFn in favor of MintFn, `keeper.DefaultMintFn` wrapper must be used in order to continue using it in `NewAppModule`. This is not breaking for depinject users, as both `MintFn` and `InflationCalculationFn` are accepted. * [#19367](https://github.com/cosmos/cosmos-sdk/pull/19398) `appmodule.Environment` is received on the Keeper to get access to different application services. - -### Bug Fixes +* [#21858](https://github.com/cosmos/cosmos-sdk/pull/21858) `NewKeeper` now returns a pointer to `Keeper`. +* [#21858](https://github.com/cosmos/cosmos-sdk/pull/21858) `DefaultMintFn` now takes `StakingKeeper` and `MintKeeper` as arguments to avoid staking keeper being required by mint. + * `SetMintFn` is used to replace the default minting function. + * `InflationCalculationFn` is not passed through depinject any longer, a MintFn is required instead. diff --git a/x/mint/depinject.go b/x/mint/depinject.go index e580cc096ca6..db36920101d5 100644 --- a/x/mint/depinject.go +++ b/x/mint/depinject.go @@ -1,6 +1,8 @@ package mint import ( + "fmt" + modulev1 "cosmossdk.io/api/cosmos/mint/module/v1" "cosmossdk.io/core/appmodule" "cosmossdk.io/depinject" @@ -21,28 +23,25 @@ func (am AppModule) IsOnePerModuleType() {} func init() { appconfig.RegisterModule(&modulev1.Module{}, appconfig.Provide(ProvideModule), + appconfig.Invoke(InvokeSetMintFn), ) } type ModuleInputs struct { depinject.In - ModuleKey depinject.OwnModuleKey - Config *modulev1.Module - Environment appmodule.Environment - Cdc codec.Codec - MintFn types.MintFn `optional:"true"` - InflationCalculationFn types.InflationCalculationFn `optional:"true"` // deprecated + Config *modulev1.Module + Environment appmodule.Environment + Cdc codec.Codec AccountKeeper types.AccountKeeper BankKeeper types.BankKeeper - StakingKeeper types.StakingKeeper } type ModuleOutputs struct { depinject.Out - MintKeeper keeper.Keeper + MintKeeper *keeper.Keeper Module appmodule.AppModule EpochHooks epochstypes.EpochHooksWrapper } @@ -67,28 +66,23 @@ func ProvideModule(in ModuleInputs) ModuleOutputs { k := keeper.NewKeeper( in.Cdc, in.Environment, - in.StakingKeeper, in.AccountKeeper, in.BankKeeper, feeCollectorName, as, ) - if in.MintFn != nil && in.InflationCalculationFn != nil { - panic("MintFn and InflationCalculationFn cannot both be set") - } + m := NewAppModule(in.Cdc, k, in.AccountKeeper) - // if no mintFn is provided, use the default minting function - if in.MintFn == nil { - // if no inflationCalculationFn is provided, use the default inflation calculation function - if in.InflationCalculationFn == nil { - in.InflationCalculationFn = types.DefaultInflationCalculationFn - } + return ModuleOutputs{MintKeeper: k, Module: m, EpochHooks: epochstypes.EpochHooksWrapper{EpochHooks: m}} +} - in.MintFn = k.DefaultMintFn(in.InflationCalculationFn) +func InvokeSetMintFn(mintKeeper *keeper.Keeper, mintFn types.MintFn, stakingKeeper types.StakingKeeper) error { + if mintFn == nil && stakingKeeper == nil { + return fmt.Errorf("custom minting function or staking keeper must be supplied or available") + } else if mintFn == nil { + mintFn = keeper.DefaultMintFn(types.DefaultInflationCalculationFn, stakingKeeper, mintKeeper) } - m := NewAppModule(in.Cdc, k, in.AccountKeeper, in.MintFn) - - return ModuleOutputs{MintKeeper: k, Module: m, EpochHooks: epochstypes.EpochHooksWrapper{EpochHooks: m}} + return mintKeeper.SetMintFn(mintFn) } diff --git a/x/mint/epoch_hooks.go b/x/mint/epoch_hooks.go index f2a3daf0d8db..d4d9fbe572b9 100644 --- a/x/mint/epoch_hooks.go +++ b/x/mint/epoch_hooks.go @@ -17,7 +17,7 @@ func (am AppModule) BeforeEpochStart(ctx context.Context, epochIdentifier string oldMinter := minter - err = am.mintFn(ctx, am.keeper.Environment, &minter, epochIdentifier, epochNumber) + err = am.keeper.MintFn(ctx, &minter, epochIdentifier, epochNumber) if err != nil { return err } diff --git a/x/mint/go.mod b/x/mint/go.mod index 5bbfae401ba9..b0343d16ef05 100644 --- a/x/mint/go.mod +++ b/x/mint/go.mod @@ -3,10 +3,10 @@ module cosmossdk.io/x/mint go 1.23.1 require ( - cosmossdk.io/api v0.7.5 + cosmossdk.io/api v0.7.6 cosmossdk.io/collections v0.4.0 - cosmossdk.io/core v1.0.0-alpha.2 - cosmossdk.io/core/testing v0.0.0-00010101000000-000000000000 + cosmossdk.io/core v1.0.0-alpha.4 + cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29 cosmossdk.io/depinject v1.0.0 cosmossdk.io/errors v1.0.1 cosmossdk.io/log v1.4.1 @@ -21,15 +21,15 @@ require ( github.com/golang/protobuf v1.5.4 github.com/grpc-ecosystem/grpc-gateway v1.16.0 github.com/stretchr/testify v1.9.0 - google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 - google.golang.org/grpc v1.66.2 - gotest.tools/v3 v3.5.1 + google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 + google.golang.org/grpc v1.67.1 + gotest.tools/v3 v3.5.1 // indirect ) require ( buf.build/gen/go/cometbft/cometbft/protocolbuffers/go v1.34.2-20240701160653-fedbb9acfd2f.2 // indirect buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.34.2-20240130113600-88ef6483f90f.2 // indirect - cosmossdk.io/schema v0.2.0 // indirect + cosmossdk.io/schema v0.3.1-0.20240930054013-7c6e0388a3f9 // indirect cosmossdk.io/x/bank v0.0.0-20240226161501-23359a0b6d91 // indirect cosmossdk.io/x/staking v0.0.0-00010101000000-000000000000 // indirect cosmossdk.io/x/tx v0.13.3 // indirect @@ -50,7 +50,6 @@ require ( github.com/cometbft/cometbft v1.0.0-rc1.0.20240908111210-ab0be101882f // indirect github.com/cometbft/cometbft-db v0.15.0 // indirect github.com/cosmos/btcutil v1.0.5 // indirect - github.com/cosmos/cosmos-db v1.0.3-0.20240911104526-ddc3f09bfc22 // indirect github.com/cosmos/crypto v0.1.2 // indirect github.com/cosmos/go-bip39 v1.0.0 // indirect github.com/cosmos/gogogateway v1.2.0 // indirect @@ -95,7 +94,7 @@ require ( github.com/hashicorp/hcl v1.0.0 // indirect github.com/hashicorp/yamux v0.1.1 // indirect github.com/hdevalence/ed25519consensus v0.2.0 // indirect - github.com/huandu/skiplist v1.2.0 // indirect + github.com/huandu/skiplist v1.2.1 // indirect github.com/iancoleman/strcase v0.3.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jmhodges/levigo v1.0.0 // indirect @@ -118,9 +117,9 @@ require ( github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/client_golang v1.20.3 // indirect + github.com/prometheus/client_golang v1.20.4 // indirect github.com/prometheus/client_model v0.6.1 // indirect - github.com/prometheus/common v0.59.1 // indirect + github.com/prometheus/common v0.60.0 // indirect github.com/prometheus/procfs v0.15.1 // indirect github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect github.com/rogpeppe/go-internal v1.12.0 // indirect @@ -157,7 +156,7 @@ require ( golang.org/x/text v0.18.0 // indirect golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f // indirect google.golang.org/protobuf v1.34.2 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect @@ -168,6 +167,7 @@ require ( require ( github.com/cockroachdb/fifo v0.0.0-20240606204812-0bbfbd93a7ce // indirect github.com/cometbft/cometbft/api v1.0.0-rc.1 // indirect + github.com/cosmos/cosmos-db v1.0.3-0.20240911104526-ddc3f09bfc22 // indirect github.com/google/uuid v1.6.0 // indirect ) @@ -176,7 +176,6 @@ replace github.com/cosmos/cosmos-sdk => ../../. // TODO remove post spinning out all modules replace ( cosmossdk.io/api => ../../api - cosmossdk.io/core/testing => ../../core/testing cosmossdk.io/store => ../../store cosmossdk.io/x/bank => ../bank cosmossdk.io/x/consensus => ../consensus diff --git a/x/mint/go.sum b/x/mint/go.sum index a658644fd79f..c9df997e10ec 100644 --- a/x/mint/go.sum +++ b/x/mint/go.sum @@ -6,8 +6,10 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cosmossdk.io/collections v0.4.0 h1:PFmwj2W8szgpD5nOd8GWH6AbYNi1f2J6akWXJ7P5t9s= cosmossdk.io/collections v0.4.0/go.mod h1:oa5lUING2dP+gdDquow+QjlF45eL1t4TJDypgGd+tv0= -cosmossdk.io/core v1.0.0-alpha.2 h1:epU0Xwces4Rgl5bMhHHkXGaGDcyucNGlC/JDH+Suckg= -cosmossdk.io/core v1.0.0-alpha.2/go.mod h1:abgLjeFLhtuKIYZWSPlVUgQBrKObO7ULV35KYfexE90= +cosmossdk.io/core v1.0.0-alpha.4 h1:9iuroT9ejDYETCsGkzkvs/wAY/5UFl7nCIINFRxyMJY= +cosmossdk.io/core v1.0.0-alpha.4/go.mod h1:3u9cWq1FAVtiiCrDPpo4LhR+9V6k/ycSG4/Y/tREWCY= +cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29 h1:NxxUo0GMJUbIuVg0R70e3cbn9eFTEuMr7ev1AFvypdY= +cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29/go.mod h1:8s2tPeJtSiQuoyPmr2Ag7meikonISO4Fv4MoO8+ORrs= cosmossdk.io/depinject v1.0.0 h1:dQaTu6+O6askNXO06+jyeUAnF2/ssKwrrszP9t5q050= cosmossdk.io/depinject v1.0.0/go.mod h1:zxK/h3HgHoA/eJVtiSsoaRaRA2D5U4cJ5thIG4ssbB8= cosmossdk.io/errors v1.0.1 h1:bzu+Kcr0kS/1DuPBtUFdWjzLqyUuCiyHjyJB6srBV/0= @@ -16,8 +18,8 @@ cosmossdk.io/log v1.4.1 h1:wKdjfDRbDyZRuWa8M+9nuvpVYxrEOwbD/CA8hvhU8QM= cosmossdk.io/log v1.4.1/go.mod h1:k08v0Pyq+gCP6phvdI6RCGhLf/r425UT6Rk/m+o74rU= cosmossdk.io/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE= cosmossdk.io/math v1.3.0/go.mod h1:vnRTxewy+M7BtXBNFybkuhSH4WfedVAAnERHgVFhp3k= -cosmossdk.io/schema v0.2.0 h1:UH5CR1DqUq8yP+5Np8PbvG4YX0zAUsTN2Qk6yThmfMk= -cosmossdk.io/schema v0.2.0/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= +cosmossdk.io/schema v0.3.1-0.20240930054013-7c6e0388a3f9 h1:DmOoS/1PeY6Ih0hAVlJ69kLMUrLV+TCbfICrZtB1vdU= +cosmossdk.io/schema v0.3.1-0.20240930054013-7c6e0388a3f9/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMbk2FiG/kXiLl8BRyzTWDw7gX/Hz7Dd5eDMs= @@ -292,8 +294,8 @@ github.com/hdevalence/ed25519consensus v0.2.0/go.mod h1:w3BHWjwJbFU29IRHL1Iqkw3s github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/huandu/go-assert v1.1.5 h1:fjemmA7sSfYHJD7CUqs9qTwwfdNAx7/j2/ZlHXzNB3c= github.com/huandu/go-assert v1.1.5/go.mod h1:yOLvuqZwmcHIC5rIzrBhT7D3Q9c3GFnd0JrPVhn/06U= -github.com/huandu/skiplist v1.2.0 h1:gox56QD77HzSC0w+Ws3MH3iie755GBJU1OER3h5VsYw= -github.com/huandu/skiplist v1.2.0/go.mod h1:7v3iFjLcSAzO4fN5B8dvebvo/qsfumiLiDXMrPiHF9w= +github.com/huandu/skiplist v1.2.1 h1:dTi93MgjwErA/8idWTzIw4Y1kZsMWx35fmI2c8Rij7w= +github.com/huandu/skiplist v1.2.1/go.mod h1:7v3iFjLcSAzO4fN5B8dvebvo/qsfumiLiDXMrPiHF9w= github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI= github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= @@ -402,8 +404,8 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= -github.com/prometheus/client_golang v1.20.3 h1:oPksm4K8B+Vt35tUhw6GbSNSgVlVSBH0qELP/7u83l4= -github.com/prometheus/client_golang v1.20.3/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_golang v1.20.4 h1:Tgh3Yr67PaOv/uTqloMsCEdeuFTatm5zIq5+qNN23vI= +github.com/prometheus/client_golang v1.20.4/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -412,8 +414,8 @@ github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= -github.com/prometheus/common v0.59.1 h1:LXb1quJHWm1P6wq/U824uxYi4Sg0oGvNeUm1z5dJoX0= -github.com/prometheus/common v0.59.1/go.mod h1:GpWM7dewqmVYcd7SmRaiWVe9SSqjf0UrwnYnpEZNuT0= +github.com/prometheus/common v0.60.0 h1:+V9PAREWNvJMAuJ1x1BaWl9dewMW4YrHZQbx0sJNllA= +github.com/prometheus/common v0.60.0/go.mod h1:h0LYf1R1deLSKtD4Vdg8gy4RuOvENW2J/h19V5NADQw= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/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= @@ -636,10 +638,10 @@ google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEY google.golang.org/genproto v0.0.0-20220314164441-57ef72a4c106/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E= google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de h1:F6qOa9AZTYJXOUEr4jDysRDLrm4PHePlge4v4TGAlxY= google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:VUhTRKeHn9wwcdrk73nvdC9gF178Tzhmt/qyaFcPLSo= -google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 h1:+rdxYoE3E5htTEWIe15GlN6IfvbURM//Jt0mmkmm6ZU= -google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117/go.mod h1:OimBR/bc1wPO9iV4NC2bpyjy3VnAwZh5EBPQdtaE5oo= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:pPJltXNxVzT4pK9yD8vR9X75DaWYYmLGMsEvBfFQZzQ= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= +google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 h1:wKguEg1hsxI2/L3hUYrpo1RVi48K+uTyzKqprwLXsb8= +google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142/go.mod h1:d6be+8HhtEtucleCbxpPW9PA9XwISACu8nvpPqF0BVo= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f h1:cUMEy+8oS78BWIH9OWazBkzbr090Od9tWBNtZHkOhf0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= @@ -650,8 +652,8 @@ google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= -google.golang.org/grpc v1.66.2 h1:3QdXkuq3Bkh7w+ywLdLvM56cmGvQHUMZpiCzt6Rqaoo= -google.golang.org/grpc v1.66.2/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y= +google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E= +google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= 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= diff --git a/x/mint/keeper/abci.go b/x/mint/keeper/abci.go index e59eb1747894..b828d8b7474f 100644 --- a/x/mint/keeper/abci.go +++ b/x/mint/keeper/abci.go @@ -9,8 +9,9 @@ import ( ) // BeginBlocker mints new tokens for the previous block. -func (k Keeper) BeginBlocker(ctx context.Context, mintFn types.MintFn) error { - defer telemetry.ModuleMeasureSince(types.ModuleName, telemetry.Now(), telemetry.MetricKeyBeginBlocker) +func (k Keeper) BeginBlocker(ctx context.Context) error { + start := telemetry.Now() + defer telemetry.ModuleMeasureSince(types.ModuleName, start, telemetry.MetricKeyBeginBlocker) // fetch stored minter & params minter, err := k.Minter.Get(ctx) @@ -22,7 +23,7 @@ func (k Keeper) BeginBlocker(ctx context.Context, mintFn types.MintFn) error { // we pass -1 as epoch number to indicate that this is not an epoch minting, // but a regular block minting. Same with epoch id "block". - err = mintFn(ctx, k.Environment, &minter, "block", -1) + err = k.MintFn(ctx, &minter, "block", -1) if err != nil { return err } diff --git a/x/mint/keeper/genesis_test.go b/x/mint/keeper/genesis_test.go index 839ca62bcc98..4c1b17ccafa2 100644 --- a/x/mint/keeper/genesis_test.go +++ b/x/mint/keeper/genesis_test.go @@ -1,12 +1,14 @@ package keeper_test import ( + "context" "testing" "github.com/golang/mock/gomock" "github.com/stretchr/testify/suite" "cosmossdk.io/collections" + "cosmossdk.io/core/appmodule" "cosmossdk.io/log" "cosmossdk.io/math" storetypes "cosmossdk.io/store/types" @@ -30,7 +32,7 @@ type GenesisTestSuite struct { suite.Suite sdkCtx sdk.Context - keeper keeper.Keeper + keeper *keeper.Keeper cdc codec.BinaryCodec accountKeeper types.AccountKeeper key *storetypes.KVStoreKey @@ -51,14 +53,17 @@ func (s *GenesisTestSuite) SetupTest() { s.sdkCtx = testCtx.Ctx s.key = key - stakingKeeper := minttestutil.NewMockStakingKeeper(ctrl) accountKeeper := minttestutil.NewMockAccountKeeper(ctrl) bankKeeper := minttestutil.NewMockBankKeeper(ctrl) s.accountKeeper = accountKeeper accountKeeper.EXPECT().GetModuleAddress(minterAcc.Name).Return(minterAcc.GetAddress()) accountKeeper.EXPECT().GetModuleAccount(s.sdkCtx, minterAcc.Name).Return(minterAcc) - s.keeper = keeper.NewKeeper(s.cdc, runtime.NewEnvironment(runtime.NewKVStoreService(key), log.NewNopLogger()), stakingKeeper, accountKeeper, bankKeeper, "", "") + s.keeper = keeper.NewKeeper(s.cdc, runtime.NewEnvironment(runtime.NewKVStoreService(key), log.NewNopLogger()), accountKeeper, bankKeeper, "", "") + err := s.keeper.SetMintFn(func(ctx context.Context, env appmodule.Environment, minter *types.Minter, epochId string, epochNumber int64) error { + return nil + }) + s.NoError(err) } func (s *GenesisTestSuite) TestImportExportGenesis() { diff --git a/x/mint/keeper/grpc_query.go b/x/mint/keeper/grpc_query.go index 162be9343b32..ad04f6077767 100644 --- a/x/mint/keeper/grpc_query.go +++ b/x/mint/keeper/grpc_query.go @@ -8,12 +8,12 @@ import ( var _ types.QueryServer = queryServer{} -func NewQueryServerImpl(k Keeper) types.QueryServer { +func NewQueryServerImpl(k *Keeper) types.QueryServer { return queryServer{k} } type queryServer struct { - k Keeper + k *Keeper } // Params returns params of the mint module. diff --git a/x/mint/keeper/grpc_query_test.go b/x/mint/keeper/grpc_query_test.go index cc941f877883..75b17808af0a 100644 --- a/x/mint/keeper/grpc_query_test.go +++ b/x/mint/keeper/grpc_query_test.go @@ -28,7 +28,7 @@ type MintTestSuite struct { ctx sdk.Context queryClient types.QueryClient - mintKeeper keeper.Keeper + mintKeeper *keeper.Keeper } func (suite *MintTestSuite) SetupTest() { @@ -42,14 +42,12 @@ func (suite *MintTestSuite) SetupTest() { ctrl := gomock.NewController(suite.T()) accountKeeper := minttestutil.NewMockAccountKeeper(ctrl) bankKeeper := minttestutil.NewMockBankKeeper(ctrl) - stakingKeeper := minttestutil.NewMockStakingKeeper(ctrl) accountKeeper.EXPECT().GetModuleAddress("mint").Return(sdk.AccAddress{}) suite.mintKeeper = keeper.NewKeeper( encCfg.Codec, env, - stakingKeeper, accountKeeper, bankKeeper, authtypes.FeeCollectorName, diff --git a/x/mint/keeper/keeper.go b/x/mint/keeper/keeper.go index 14ee19cde865..5bb607c0449c 100644 --- a/x/mint/keeper/keeper.go +++ b/x/mint/keeper/keeper.go @@ -20,7 +20,6 @@ type Keeper struct { appmodule.Environment cdc codec.BinaryCodec - stakingKeeper types.StakingKeeper bankKeeper types.BankKeeper feeCollectorName string // the address capable of executing a MsgUpdateParams message. Typically, this @@ -30,18 +29,21 @@ type Keeper struct { Schema collections.Schema Params collections.Item[types.Params] Minter collections.Item[types.Minter] + + // mintFn is used to mint new coins during BeginBlock. This function is in charge of + // minting new coins based on arbitrary logic, previously done through InflationCalculationFn. + mintFn types.MintFn } // NewKeeper creates a new mint Keeper instance func NewKeeper( cdc codec.BinaryCodec, env appmodule.Environment, - sk types.StakingKeeper, ak types.AccountKeeper, bk types.BankKeeper, feeCollectorName string, authority string, -) Keeper { +) *Keeper { // ensure mint module account is set if addr := ak.GetModuleAddress(types.ModuleName); addr == nil { panic(fmt.Sprintf("the x/%s module account has not been set", types.ModuleName)) @@ -51,7 +53,6 @@ func NewKeeper( k := Keeper{ Environment: env, cdc: cdc, - stakingKeeper: sk, bankKeeper: bk, feeCollectorName: feeCollectorName, authority: authority, @@ -64,29 +65,25 @@ func NewKeeper( panic(err) } k.Schema = schema - return k -} -// GetAuthority returns the x/mint module's authority. -func (k Keeper) GetAuthority() string { - return k.authority + return &k } -// StakingTokenSupply implements an alias call to the underlying staking keeper's -// StakingTokenSupply to be used in BeginBlocker. -func (k Keeper) StakingTokenSupply(ctx context.Context) (math.Int, error) { - return k.stakingKeeper.StakingTokenSupply(ctx) +// SetMintFn is used to mint new coins during BeginBlock. The mintFn function is in charge of +// minting new coins based on arbitrary logic, previously done through InflationCalculationFn. +func (k *Keeper) SetMintFn(mintFn types.MintFn) error { + k.mintFn = mintFn + return nil } -// BondedRatio implements an alias call to the underlying staking keeper's -// BondedRatio to be used in BeginBlocker. -func (k Keeper) BondedRatio(ctx context.Context) (math.LegacyDec, error) { - return k.stakingKeeper.BondedRatio(ctx) +// GetAuthority returns the x/mint module's authority. +func (k *Keeper) GetAuthority() string { + return k.authority } // MintCoins implements an alias call to the underlying supply keeper's // MintCoins to be used in BeginBlocker. -func (k Keeper) MintCoins(ctx context.Context, newCoins sdk.Coins) error { +func (k *Keeper) MintCoins(ctx context.Context, newCoins sdk.Coins) error { if newCoins.Empty() { // skip as no coins need to be minted return nil @@ -97,11 +94,17 @@ func (k Keeper) MintCoins(ctx context.Context, newCoins sdk.Coins) error { // AddCollectedFees implements an alias call to the underlying supply keeper's // AddCollectedFees to be used in BeginBlocker. -func (k Keeper) AddCollectedFees(ctx context.Context, fees sdk.Coins) error { +func (k *Keeper) AddCollectedFees(ctx context.Context, fees sdk.Coins) error { return k.bankKeeper.SendCoinsFromModuleToModule(ctx, types.ModuleName, k.feeCollectorName, fees) } -func (k Keeper) DefaultMintFn(ic types.InflationCalculationFn) types.MintFn { +func (k *Keeper) MintFn(ctx context.Context, minter *types.Minter, epochId string, epochNumber int64) error { + return k.mintFn(ctx, k.Environment, minter, epochId, epochNumber) +} + +// DefaultMintFn returns a default mint function. It requires the Staking module and the mint keeper. +// The default Mintfn has a requirement on staking as it uses bond to calculate inflation. +func DefaultMintFn(ic types.InflationCalculationFn, staking types.StakingKeeper, k *Keeper) types.MintFn { return func(ctx context.Context, env appmodule.Environment, minter *types.Minter, epochId string, epochNumber int64) error { // the default mint function is called every block, so we only check if epochId is "block" which is // a special value to indicate that this is not an epoch minting, but a regular block minting. @@ -109,12 +112,12 @@ func (k Keeper) DefaultMintFn(ic types.InflationCalculationFn) types.MintFn { return nil } - stakingTokenSupply, err := k.StakingTokenSupply(ctx) + stakingTokenSupply, err := staking.StakingTokenSupply(ctx) if err != nil { return err } - bondedRatio, err := k.BondedRatio(ctx) + bondedRatio, err := staking.BondedRatio(ctx) if err != nil { return err } diff --git a/x/mint/keeper/keeper_test.go b/x/mint/keeper/keeper_test.go index 454967c1fc06..6bec00095a18 100644 --- a/x/mint/keeper/keeper_test.go +++ b/x/mint/keeper/keeper_test.go @@ -29,7 +29,7 @@ const govModuleNameStr = "cosmos10d07y265gmmuvt4z0w9aw880jnsr700j6zn9kn" type KeeperTestSuite struct { suite.Suite - mintKeeper keeper.Keeper + mintKeeper *keeper.Keeper ctx sdk.Context msgServer types.MsgServer stakingKeeper *minttestutil.MockStakingKeeper @@ -59,7 +59,6 @@ func (s *KeeperTestSuite) SetupTest() { s.mintKeeper = keeper.NewKeeper( encCfg.Codec, env, - stakingKeeper, accountKeeper, bankKeeper, authtypes.FeeCollectorName, @@ -75,40 +74,19 @@ func (s *KeeperTestSuite) SetupTest() { s.msgServer = keeper.NewMsgServerImpl(s.mintKeeper) } -func (s *KeeperTestSuite) TestAliasFunctions() { - stakingTokenSupply := math.NewIntFromUint64(100000000000) - s.stakingKeeper.EXPECT().StakingTokenSupply(s.ctx).Return(stakingTokenSupply, nil) - tokenSupply, err := s.mintKeeper.StakingTokenSupply(s.ctx) - s.NoError(err) - s.Equal(tokenSupply, stakingTokenSupply) - - bondedRatio := math.LegacyNewDecWithPrec(15, 2) - s.stakingKeeper.EXPECT().BondedRatio(s.ctx).Return(bondedRatio, nil) - ratio, err := s.mintKeeper.BondedRatio(s.ctx) - s.NoError(err) - s.Equal(ratio, bondedRatio) - - coins := sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(1000000))) - s.bankKeeper.EXPECT().MintCoins(s.ctx, types.ModuleName, coins).Return(nil) - s.Equal(s.mintKeeper.MintCoins(s.ctx, sdk.NewCoins()), nil) - s.Nil(s.mintKeeper.MintCoins(s.ctx, coins)) - - fees := sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(1000))) - s.bankKeeper.EXPECT().SendCoinsFromModuleToModule(s.ctx, types.ModuleName, authtypes.FeeCollectorName, fees).Return(nil) - s.Nil(s.mintKeeper.AddCollectedFees(s.ctx, fees)) -} - func (s *KeeperTestSuite) TestDefaultMintFn() { s.stakingKeeper.EXPECT().StakingTokenSupply(s.ctx).Return(math.NewIntFromUint64(100000000000), nil).AnyTimes() bondedRatio := math.LegacyNewDecWithPrec(15, 2) s.stakingKeeper.EXPECT().BondedRatio(s.ctx).Return(bondedRatio, nil).AnyTimes() s.bankKeeper.EXPECT().MintCoins(s.ctx, types.ModuleName, sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(792)))).Return(nil) s.bankKeeper.EXPECT().SendCoinsFromModuleToModule(s.ctx, types.ModuleName, authtypes.FeeCollectorName, gomock.Any()).Return(nil) + err := s.mintKeeper.SetMintFn(keeper.DefaultMintFn(types.DefaultInflationCalculationFn, s.stakingKeeper, s.mintKeeper)) + s.NoError(err) minter, err := s.mintKeeper.Minter.Get(s.ctx) s.NoError(err) - err = s.mintKeeper.DefaultMintFn(types.DefaultInflationCalculationFn)(s.ctx, s.mintKeeper.Environment, &minter, "block", 0) + err = s.mintKeeper.MintFn(s.ctx, &minter, "block", 0) s.NoError(err) // set a maxSupply and call again. totalSupply will be bigger than maxSupply. @@ -118,7 +96,7 @@ func (s *KeeperTestSuite) TestDefaultMintFn() { err = s.mintKeeper.Params.Set(s.ctx, params) s.NoError(err) - err = s.mintKeeper.DefaultMintFn(types.DefaultInflationCalculationFn)(s.ctx, s.mintKeeper.Environment, &minter, "block", 0) + err = s.mintKeeper.MintFn(s.ctx, &minter, "block", 0) s.NoError(err) // modify max supply to be almost reached @@ -134,7 +112,7 @@ func (s *KeeperTestSuite) TestDefaultMintFn() { s.bankKeeper.EXPECT().MintCoins(s.ctx, types.ModuleName, sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(2000)))).Return(nil) s.bankKeeper.EXPECT().SendCoinsFromModuleToModule(s.ctx, types.ModuleName, authtypes.FeeCollectorName, gomock.Any()).Return(nil) - err = s.mintKeeper.DefaultMintFn(types.DefaultInflationCalculationFn)(s.ctx, s.mintKeeper.Environment, &minter, "block", 0) + err = s.mintKeeper.MintFn(s.ctx, &minter, "block", 0) s.NoError(err) } @@ -144,12 +122,13 @@ func (s *KeeperTestSuite) TestBeginBlocker() { s.stakingKeeper.EXPECT().BondedRatio(s.ctx).Return(bondedRatio, nil).AnyTimes() s.bankKeeper.EXPECT().MintCoins(s.ctx, types.ModuleName, sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(792)))).Return(nil) s.bankKeeper.EXPECT().SendCoinsFromModuleToModule(s.ctx, types.ModuleName, authtypes.FeeCollectorName, gomock.Any()).Return(nil) - + err := s.mintKeeper.SetMintFn(keeper.DefaultMintFn(types.DefaultInflationCalculationFn, s.stakingKeeper, s.mintKeeper)) + s.NoError(err) // get minter (it should get modified afterwards) minter, err := s.mintKeeper.Minter.Get(s.ctx) s.NoError(err) - err = s.mintKeeper.BeginBlocker(s.ctx, s.mintKeeper.DefaultMintFn(types.DefaultInflationCalculationFn)) + err = s.mintKeeper.BeginBlocker(s.ctx) s.NoError(err) // get minter again and compare @@ -158,10 +137,12 @@ func (s *KeeperTestSuite) TestBeginBlocker() { s.NotEqual(minter, newMinter) // now use a mintfn that doesn't do anything - err = s.mintKeeper.BeginBlocker(s.ctx, func(ctx context.Context, env appmodule.Environment, minter *types.Minter, epochId string, epochNumber int64) error { + err = s.mintKeeper.SetMintFn(func(ctx context.Context, env appmodule.Environment, minter *types.Minter, epochId string, epochNumber int64) error { return nil }) s.NoError(err) + err = s.mintKeeper.BeginBlocker(s.ctx) + s.NoError(err) // get minter again and compare unchangedMinter, err := s.mintKeeper.Minter.Get(s.ctx) diff --git a/x/mint/keeper/migrator.go b/x/mint/keeper/migrator.go index 199757c1f1a2..7677fd37c96c 100644 --- a/x/mint/keeper/migrator.go +++ b/x/mint/keeper/migrator.go @@ -8,11 +8,11 @@ import ( // Migrator is a struct for handling in-place state migrations. type Migrator struct { - keeper Keeper + keeper *Keeper } // NewMigrator returns Migrator instance for the state migration. -func NewMigrator(k Keeper) Migrator { +func NewMigrator(k *Keeper) Migrator { return Migrator{ keeper: k, } diff --git a/x/mint/keeper/msg_server.go b/x/mint/keeper/msg_server.go index 98cf65ac6323..ea72c333dc88 100644 --- a/x/mint/keeper/msg_server.go +++ b/x/mint/keeper/msg_server.go @@ -11,11 +11,11 @@ var _ types.MsgServer = msgServer{} // msgServer is a wrapper of Keeper. type msgServer struct { - Keeper + *Keeper } // NewMsgServerImpl returns an implementation of the x/mint MsgServer interface. -func NewMsgServerImpl(k Keeper) types.MsgServer { +func NewMsgServerImpl(k *Keeper) types.MsgServer { return &msgServer{ Keeper: k, } diff --git a/x/mint/keeper/msg_server_test.go b/x/mint/keeper/msg_server_test.go index 10423e26e2c6..602b4a2fbf36 100644 --- a/x/mint/keeper/msg_server_test.go +++ b/x/mint/keeper/msg_server_test.go @@ -61,7 +61,6 @@ func (s *KeeperTestSuite) TestUpdateParams() { } for _, tc := range testCases { - tc := tc s.Run(tc.name, func() { _, err := s.msgServer.UpdateParams(s.ctx, tc.request) if tc.expectErr { diff --git a/x/mint/module.go b/x/mint/module.go index fa27a6838df2..52c6324b4a11 100644 --- a/x/mint/module.go +++ b/x/mint/module.go @@ -16,6 +16,7 @@ import ( "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/codec" + simsx "github.com/cosmos/cosmos-sdk/simsx" "github.com/cosmos/cosmos-sdk/types/module" simtypes "github.com/cosmos/cosmos-sdk/types/simulation" ) @@ -38,34 +39,21 @@ var ( // AppModule implements an application module for the mint module. type AppModule struct { cdc codec.Codec - keeper keeper.Keeper + keeper *keeper.Keeper authKeeper types.AccountKeeper - - // mintFn is used to mint new coins during BeginBlock. This function is in charge of - // minting new coins based on arbitrary logic, previously done through InflationCalculationFn. - // If mintFn is nil, the default minting logic is used. - mintFn types.MintFn } // NewAppModule creates a new AppModule object. // If the mintFn argument is nil, then the default minting function will be used. func NewAppModule( cdc codec.Codec, - keeper keeper.Keeper, + keeper *keeper.Keeper, ak types.AccountKeeper, - mintFn types.MintFn, ) AppModule { - // If mintFn is nil, use the default minting function. - // This check also happens in ProvideModule when used with depinject. - if mintFn == nil { - mintFn = keeper.DefaultMintFn(types.DefaultInflationCalculationFn) - } - return AppModule{ cdc: cdc, keeper: keeper, authKeeper: ak, - mintFn: mintFn, } } @@ -158,7 +146,7 @@ func (AppModule) ConsensusVersion() uint64 { return ConsensusVersion } // BeginBlock returns the begin blocker for the mint module. func (am AppModule) BeginBlock(ctx context.Context) error { - return am.keeper.BeginBlocker(ctx, am.mintFn) + return am.keeper.BeginBlocker(ctx) } // AppModuleSimulation functions @@ -168,17 +156,12 @@ func (AppModule) GenerateGenesisState(simState *module.SimulationState) { simulation.RandomizedGenState(simState) } -// ProposalMsgs returns msgs used for governance proposals for simulations. -func (AppModule) ProposalMsgs(simState module.SimulationState) []simtypes.WeightedProposalMsg { - return simulation.ProposalMsgs() +// ProposalMsgsX returns msgs used for governance proposals for simulations. +func (AppModule) ProposalMsgsX(weights simsx.WeightSource, reg simsx.Registry) { + reg.Add(weights.Get("msg_update_params", 100), simulation.MsgUpdateParamsFactory()) } // RegisterStoreDecoder registers a decoder for mint module's types. func (am AppModule) RegisterStoreDecoder(sdr simtypes.StoreDecoderRegistry) { sdr[types.StoreKey] = simtypes.NewStoreDecoderFuncFromCollectionsSchema(am.keeper.Schema) } - -// WeightedOperations doesn't return any mint module operation. -func (AppModule) WeightedOperations(_ module.SimulationState) []simtypes.WeightedOperation { - return nil -} diff --git a/x/mint/module_test.go b/x/mint/module_test.go index d1a618459dbb..1ba64d0bd8fe 100644 --- a/x/mint/module_test.go +++ b/x/mint/module_test.go @@ -27,7 +27,7 @@ const govModuleNameStr = "cosmos10d07y265gmmuvt4z0w9aw880jnsr700j6zn9kn" type ModuleTestSuite struct { suite.Suite - mintKeeper keeper.Keeper + mintKeeper *keeper.Keeper ctx sdk.Context msgServer types.MsgServer stakingKeeper *minttestutil.MockStakingKeeper @@ -59,22 +59,24 @@ func (s *ModuleTestSuite) SetupTest() { s.mintKeeper = keeper.NewKeeper( encCfg.Codec, env, - stakingKeeper, accountKeeper, bankKeeper, authtypes.FeeCollectorName, govModuleNameStr, ) + err := s.mintKeeper.SetMintFn(keeper.DefaultMintFn(types.DefaultInflationCalculationFn, stakingKeeper, s.mintKeeper)) + s.NoError(err) + s.stakingKeeper = stakingKeeper s.bankKeeper = bankKeeper - err := s.mintKeeper.Params.Set(s.ctx, types.DefaultParams()) + err = s.mintKeeper.Params.Set(s.ctx, types.DefaultParams()) s.NoError(err) s.NoError(s.mintKeeper.Minter.Set(s.ctx, types.DefaultInitialMinter())) s.msgServer = keeper.NewMsgServerImpl(s.mintKeeper) - s.appmodule = mint.NewAppModule(encCfg.Codec, s.mintKeeper, accountKeeper, s.mintKeeper.DefaultMintFn(types.DefaultInflationCalculationFn)) + s.appmodule = mint.NewAppModule(encCfg.Codec, s.mintKeeper, accountKeeper) } func (s *ModuleTestSuite) TestEpochHooks() { diff --git a/x/mint/simulation/genesis.go b/x/mint/simulation/genesis.go index 9933efa1971d..c234d27345cf 100644 --- a/x/mint/simulation/genesis.go +++ b/x/mint/simulation/genesis.go @@ -1,8 +1,6 @@ package simulation import ( - "encoding/json" - "fmt" "math/rand" "cosmossdk.io/math" @@ -70,10 +68,5 @@ func RandomizedGenState(simState *module.SimulationState) { mintGenesis := types.NewGenesisState(types.InitialMinter(inflation), params) - bz, err := json.MarshalIndent(&mintGenesis, "", " ") - if err != nil { - panic(err) - } - fmt.Printf("Selected randomly generated minting parameters:\n%s\n", bz) simState.GenState[types.ModuleName] = simState.Cdc.MustMarshalJSON(mintGenesis) } diff --git a/x/mint/simulation/msg_factory.go b/x/mint/simulation/msg_factory.go new file mode 100644 index 000000000000..45c96359f61e --- /dev/null +++ b/x/mint/simulation/msg_factory.go @@ -0,0 +1,29 @@ +package simulation + +import ( + "context" + + sdkmath "cosmossdk.io/math" + "cosmossdk.io/x/mint/types" + + "github.com/cosmos/cosmos-sdk/simsx" +) + +// MsgUpdateParamsFactory creates a gov proposal for param updates +func MsgUpdateParamsFactory() simsx.SimMsgFactoryFn[*types.MsgUpdateParams] { + return func(_ context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter) ([]simsx.SimAccount, *types.MsgUpdateParams) { + r := testData.Rand() + params := types.DefaultParams() + params.BlocksPerYear = r.Uint64InRange(1, 1_000_000) + params.GoalBonded = sdkmath.LegacyNewDecWithPrec(int64(r.IntInRange(1, 100)), 2) + params.InflationMin = sdkmath.LegacyNewDecWithPrec(int64(r.IntInRange(1, 50)), 2) + params.InflationMax = sdkmath.LegacyNewDecWithPrec(int64(r.IntInRange(50, 100)), 2) + params.InflationRateChange = sdkmath.LegacyNewDecWithPrec(int64(r.IntInRange(1, 100)), 2) + params.MintDenom = r.StringN(10) + + return nil, &types.MsgUpdateParams{ + Authority: testData.ModuleAccountAddress(reporter, "gov"), + Params: params, + } + } +} diff --git a/x/mint/simulation/proposals_test.go b/x/mint/simulation/proposals_test.go deleted file mode 100644 index abc470a76d81..000000000000 --- a/x/mint/simulation/proposals_test.go +++ /dev/null @@ -1,52 +0,0 @@ -package simulation_test - -import ( - "context" - "math/rand" - "testing" - - "gotest.tools/v3/assert" - - sdkmath "cosmossdk.io/math" - "cosmossdk.io/x/mint/simulation" - "cosmossdk.io/x/mint/types" - - codectestutil "github.com/cosmos/cosmos-sdk/codec/testutil" - "github.com/cosmos/cosmos-sdk/types/address" - simtypes "github.com/cosmos/cosmos-sdk/types/simulation" -) - -func TestProposalMsgs(t *testing.T) { - ac := codectestutil.CodecOptions{}.GetAddressCodec() - // initialize parameters - s := rand.NewSource(1) - r := rand.New(s) - - accounts := simtypes.RandomAccounts(r, 3) - - // execute ProposalMsgs function - weightedProposalMsgs := simulation.ProposalMsgs() - assert.Assert(t, len(weightedProposalMsgs) == 1) - - w0 := weightedProposalMsgs[0] - - // tests w0 interface: - assert.Equal(t, simulation.OpWeightMsgUpdateParams, w0.AppParamsKey()) - assert.Equal(t, simulation.DefaultWeightMsgUpdateParams, w0.DefaultWeight()) - - msg, err := w0.MsgSimulatorFn()(context.Background(), r, accounts, ac) - assert.NilError(t, err) - msgUpdateParams, ok := msg.(*types.MsgUpdateParams) - assert.Assert(t, ok) - - authority, err := ac.BytesToString(address.Module("gov")) - assert.NilError(t, err) - - assert.Equal(t, authority, msgUpdateParams.Authority) - assert.Equal(t, uint64(122877), msgUpdateParams.Params.BlocksPerYear) - assert.DeepEqual(t, sdkmath.LegacyNewDecWithPrec(95, 2), msgUpdateParams.Params.GoalBonded) - assert.DeepEqual(t, sdkmath.LegacyNewDecWithPrec(94, 2), msgUpdateParams.Params.InflationMax) - assert.DeepEqual(t, sdkmath.LegacyNewDecWithPrec(23, 2), msgUpdateParams.Params.InflationMin) - assert.DeepEqual(t, sdkmath.LegacyNewDecWithPrec(89, 2), msgUpdateParams.Params.InflationRateChange) - assert.Equal(t, "XhhuTSkuxK", msgUpdateParams.Params.MintDenom) -} diff --git a/x/nft/README.md b/x/nft/README.md index 34c1d40660b9..3bf1b6b41b44 100644 --- a/x/nft/README.md +++ b/x/nft/README.md @@ -22,6 +22,8 @@ sidebar_position: 1 * [Messages](#messages) * [MsgSend](#msgsend) * [Events](#events) +* [Queries](#queries) +* [Keeper Functions](#keeper-functions) ## Concepts @@ -86,4 +88,30 @@ The message handling should fail if: ## Events -The nft module emits proto events defined in [the Protobuf reference](https://buf.build/cosmos/cosmos-sdk/docs/main:cosmos.nft.v1beta1). +The NFT module emits proto events defined in [the Protobuf reference](https://buf.build/cosmos/cosmos-sdk/docs/main:cosmos.nft.v1beta1). + +## Queries + +The `x/nft` module provides several queries to retrieve information about NFTs and classes: + +* `Balance`: Returns the number of NFTs of a given class owned by the owner. +* `Owner`: Returns the owner of an NFT based on its class and ID. +* `Supply`: Returns the number of NFTs from the given class. +* `NFTs`: Queries all NFTs of a given class or owner. +* `NFT`: Returns an NFT based on its class and ID. +* `Class`: Returns an NFT class based on its ID. +* `Classes`: Returns all NFT classes. + +## Keeper Functions + +The Keeper of the `x/nft` module provides several functions to manage NFTs: + +* `Mint`: Mints a new NFT. +* `Burn`: Burns an existing NFT. +* `Update`: Updates an existing NFT. +* `Transfer`: Transfers an NFT from one owner to another. +* `GetNFT`: Retrieves information about a specific NFT. +* `GetNFTsOfClass`: Retrieves all NFTs of a specific class. +* `GetNFTsOfClassByOwner`: Retrieves all NFTs of a specific class belonging to an owner. +* `GetBalance`: Retrieves the balance of NFTs of a specific class for an owner. +* `GetTotalSupply`: Retrieves the total supply of NFTs of a specific class. diff --git a/x/nft/go.mod b/x/nft/go.mod index d312004db04f..baca50bed955 100644 --- a/x/nft/go.mod +++ b/x/nft/go.mod @@ -3,8 +3,8 @@ module cosmossdk.io/x/nft go 1.23.1 require ( - cosmossdk.io/api v0.7.5 - cosmossdk.io/core v1.0.0-alpha.2 + cosmossdk.io/api v0.7.6 + cosmossdk.io/core v1.0.0-alpha.4 cosmossdk.io/depinject v1.0.0 cosmossdk.io/errors v1.0.1 cosmossdk.io/log v1.4.1 @@ -17,16 +17,16 @@ require ( github.com/golang/protobuf v1.5.4 github.com/grpc-ecosystem/grpc-gateway v1.16.0 github.com/stretchr/testify v1.9.0 - google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 - google.golang.org/grpc v1.66.2 + google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 + google.golang.org/grpc v1.67.1 ) require ( buf.build/gen/go/cometbft/cometbft/protocolbuffers/go v1.34.2-20240701160653-fedbb9acfd2f.2 // indirect buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.34.2-20240130113600-88ef6483f90f.2 // indirect cosmossdk.io/collections v0.4.0 // indirect - cosmossdk.io/core/testing v0.0.0-00010101000000-000000000000 // indirect - cosmossdk.io/schema v0.2.0 // indirect + cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29 // indirect + cosmossdk.io/schema v0.3.1-0.20240930054013-7c6e0388a3f9 // indirect cosmossdk.io/x/bank v0.0.0-20240226161501-23359a0b6d91 // indirect cosmossdk.io/x/staking v0.0.0-00010101000000-000000000000 // indirect cosmossdk.io/x/tx v0.13.3 // indirect @@ -96,7 +96,7 @@ require ( github.com/hashicorp/hcl v1.0.0 // indirect github.com/hashicorp/yamux v0.1.1 // indirect github.com/hdevalence/ed25519consensus v0.2.0 // indirect - github.com/huandu/skiplist v1.2.0 // indirect + github.com/huandu/skiplist v1.2.1 // indirect github.com/iancoleman/strcase v0.3.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jmhodges/levigo v1.0.0 // indirect @@ -119,9 +119,9 @@ require ( github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/client_golang v1.20.3 // indirect + github.com/prometheus/client_golang v1.20.4 // indirect github.com/prometheus/client_model v0.6.1 // indirect - github.com/prometheus/common v0.59.1 // indirect + github.com/prometheus/common v0.60.0 // indirect github.com/prometheus/procfs v0.15.1 // indirect github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect github.com/rogpeppe/go-internal v1.12.0 // indirect @@ -158,7 +158,7 @@ require ( golang.org/x/text v0.18.0 // indirect golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f // indirect google.golang.org/protobuf v1.34.2 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect @@ -172,7 +172,6 @@ replace github.com/cosmos/cosmos-sdk => ../../. // TODO remove post spinning out all modules replace ( cosmossdk.io/api => ../../api - cosmossdk.io/core/testing => ../../core/testing cosmossdk.io/store => ../../store cosmossdk.io/x/bank => ../bank cosmossdk.io/x/staking => ../staking diff --git a/x/nft/go.sum b/x/nft/go.sum index a658644fd79f..c9df997e10ec 100644 --- a/x/nft/go.sum +++ b/x/nft/go.sum @@ -6,8 +6,10 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cosmossdk.io/collections v0.4.0 h1:PFmwj2W8szgpD5nOd8GWH6AbYNi1f2J6akWXJ7P5t9s= cosmossdk.io/collections v0.4.0/go.mod h1:oa5lUING2dP+gdDquow+QjlF45eL1t4TJDypgGd+tv0= -cosmossdk.io/core v1.0.0-alpha.2 h1:epU0Xwces4Rgl5bMhHHkXGaGDcyucNGlC/JDH+Suckg= -cosmossdk.io/core v1.0.0-alpha.2/go.mod h1:abgLjeFLhtuKIYZWSPlVUgQBrKObO7ULV35KYfexE90= +cosmossdk.io/core v1.0.0-alpha.4 h1:9iuroT9ejDYETCsGkzkvs/wAY/5UFl7nCIINFRxyMJY= +cosmossdk.io/core v1.0.0-alpha.4/go.mod h1:3u9cWq1FAVtiiCrDPpo4LhR+9V6k/ycSG4/Y/tREWCY= +cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29 h1:NxxUo0GMJUbIuVg0R70e3cbn9eFTEuMr7ev1AFvypdY= +cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29/go.mod h1:8s2tPeJtSiQuoyPmr2Ag7meikonISO4Fv4MoO8+ORrs= cosmossdk.io/depinject v1.0.0 h1:dQaTu6+O6askNXO06+jyeUAnF2/ssKwrrszP9t5q050= cosmossdk.io/depinject v1.0.0/go.mod h1:zxK/h3HgHoA/eJVtiSsoaRaRA2D5U4cJ5thIG4ssbB8= cosmossdk.io/errors v1.0.1 h1:bzu+Kcr0kS/1DuPBtUFdWjzLqyUuCiyHjyJB6srBV/0= @@ -16,8 +18,8 @@ cosmossdk.io/log v1.4.1 h1:wKdjfDRbDyZRuWa8M+9nuvpVYxrEOwbD/CA8hvhU8QM= cosmossdk.io/log v1.4.1/go.mod h1:k08v0Pyq+gCP6phvdI6RCGhLf/r425UT6Rk/m+o74rU= cosmossdk.io/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE= cosmossdk.io/math v1.3.0/go.mod h1:vnRTxewy+M7BtXBNFybkuhSH4WfedVAAnERHgVFhp3k= -cosmossdk.io/schema v0.2.0 h1:UH5CR1DqUq8yP+5Np8PbvG4YX0zAUsTN2Qk6yThmfMk= -cosmossdk.io/schema v0.2.0/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= +cosmossdk.io/schema v0.3.1-0.20240930054013-7c6e0388a3f9 h1:DmOoS/1PeY6Ih0hAVlJ69kLMUrLV+TCbfICrZtB1vdU= +cosmossdk.io/schema v0.3.1-0.20240930054013-7c6e0388a3f9/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMbk2FiG/kXiLl8BRyzTWDw7gX/Hz7Dd5eDMs= @@ -292,8 +294,8 @@ github.com/hdevalence/ed25519consensus v0.2.0/go.mod h1:w3BHWjwJbFU29IRHL1Iqkw3s github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/huandu/go-assert v1.1.5 h1:fjemmA7sSfYHJD7CUqs9qTwwfdNAx7/j2/ZlHXzNB3c= github.com/huandu/go-assert v1.1.5/go.mod h1:yOLvuqZwmcHIC5rIzrBhT7D3Q9c3GFnd0JrPVhn/06U= -github.com/huandu/skiplist v1.2.0 h1:gox56QD77HzSC0w+Ws3MH3iie755GBJU1OER3h5VsYw= -github.com/huandu/skiplist v1.2.0/go.mod h1:7v3iFjLcSAzO4fN5B8dvebvo/qsfumiLiDXMrPiHF9w= +github.com/huandu/skiplist v1.2.1 h1:dTi93MgjwErA/8idWTzIw4Y1kZsMWx35fmI2c8Rij7w= +github.com/huandu/skiplist v1.2.1/go.mod h1:7v3iFjLcSAzO4fN5B8dvebvo/qsfumiLiDXMrPiHF9w= github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI= github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= @@ -402,8 +404,8 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= -github.com/prometheus/client_golang v1.20.3 h1:oPksm4K8B+Vt35tUhw6GbSNSgVlVSBH0qELP/7u83l4= -github.com/prometheus/client_golang v1.20.3/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_golang v1.20.4 h1:Tgh3Yr67PaOv/uTqloMsCEdeuFTatm5zIq5+qNN23vI= +github.com/prometheus/client_golang v1.20.4/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -412,8 +414,8 @@ github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= -github.com/prometheus/common v0.59.1 h1:LXb1quJHWm1P6wq/U824uxYi4Sg0oGvNeUm1z5dJoX0= -github.com/prometheus/common v0.59.1/go.mod h1:GpWM7dewqmVYcd7SmRaiWVe9SSqjf0UrwnYnpEZNuT0= +github.com/prometheus/common v0.60.0 h1:+V9PAREWNvJMAuJ1x1BaWl9dewMW4YrHZQbx0sJNllA= +github.com/prometheus/common v0.60.0/go.mod h1:h0LYf1R1deLSKtD4Vdg8gy4RuOvENW2J/h19V5NADQw= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/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= @@ -636,10 +638,10 @@ google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEY google.golang.org/genproto v0.0.0-20220314164441-57ef72a4c106/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E= google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de h1:F6qOa9AZTYJXOUEr4jDysRDLrm4PHePlge4v4TGAlxY= google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:VUhTRKeHn9wwcdrk73nvdC9gF178Tzhmt/qyaFcPLSo= -google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 h1:+rdxYoE3E5htTEWIe15GlN6IfvbURM//Jt0mmkmm6ZU= -google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117/go.mod h1:OimBR/bc1wPO9iV4NC2bpyjy3VnAwZh5EBPQdtaE5oo= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:pPJltXNxVzT4pK9yD8vR9X75DaWYYmLGMsEvBfFQZzQ= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= +google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 h1:wKguEg1hsxI2/L3hUYrpo1RVi48K+uTyzKqprwLXsb8= +google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142/go.mod h1:d6be+8HhtEtucleCbxpPW9PA9XwISACu8nvpPqF0BVo= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f h1:cUMEy+8oS78BWIH9OWazBkzbr090Od9tWBNtZHkOhf0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= @@ -650,8 +652,8 @@ google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= -google.golang.org/grpc v1.66.2 h1:3QdXkuq3Bkh7w+ywLdLvM56cmGvQHUMZpiCzt6Rqaoo= -google.golang.org/grpc v1.66.2/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y= +google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E= +google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= 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= diff --git a/x/nft/module/module.go b/x/nft/module/module.go index 70672dbab19a..16b82baf2a23 100644 --- a/x/nft/module/module.go +++ b/x/nft/module/module.go @@ -17,6 +17,7 @@ import ( sdkclient "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/codec" cdctypes "github.com/cosmos/cosmos-sdk/codec/types" + "github.com/cosmos/cosmos-sdk/simsx" "github.com/cosmos/cosmos-sdk/types/module" simtypes "github.com/cosmos/cosmos-sdk/types/simulation" ) @@ -130,11 +131,6 @@ func (am AppModule) RegisterStoreDecoder(sdr simtypes.StoreDecoderRegistry) { sdr[keeper.StoreKey] = simulation.NewDecodeStore(am.cdc) } -// WeightedOperations returns the all the nft module operations with their respective weights. -func (am AppModule) WeightedOperations(simState module.SimulationState) []simtypes.WeightedOperation { - return simulation.WeightedOperations( - am.registry, - simState.AppParams, simState.Cdc, simState.TxConfig, - am.accountKeeper, am.bankKeeper, am.keeper, - ) +func (am AppModule) WeightedOperationsX(weights simsx.WeightSource, reg simsx.Registry) { + reg.Add(weights.Get("msg_send", 100), simulation.MsgSendFactory(am.keeper)) } diff --git a/x/nft/simulation/decoder_test.go b/x/nft/simulation/decoder_test.go index 7498ee7e8f58..a9dfed8862ed 100644 --- a/x/nft/simulation/decoder_test.go +++ b/x/nft/simulation/decoder_test.go @@ -75,7 +75,6 @@ func TestDecodeStore(t *testing.T) { } for i, tt := range tests { - i, tt := i, tt t.Run(tt.name, func(t *testing.T) { if tt.expectErr { require.Panics(t, func() { dec(kvPairs.Pairs[i], kvPairs.Pairs[i]) }, tt.name) diff --git a/x/nft/simulation/msg_factory.go b/x/nft/simulation/msg_factory.go new file mode 100644 index 000000000000..14db2666dee9 --- /dev/null +++ b/x/nft/simulation/msg_factory.go @@ -0,0 +1,66 @@ +package simulation + +import ( + "context" + + "cosmossdk.io/x/nft" + "cosmossdk.io/x/nft/keeper" + + "github.com/cosmos/cosmos-sdk/simsx" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +func MsgSendFactory(k keeper.Keeper) simsx.SimMsgFactoryFn[*nft.MsgSend] { + return func(ctx context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter) ([]simsx.SimAccount, *nft.MsgSend) { + from := testData.AnyAccount(reporter, simsx.WithSpendableBalance()) + to := testData.AnyAccount(reporter, simsx.ExcludeAccounts(from)) + + n, err := randNFT(ctx, testData.Rand(), k, from.Address) + if err != nil { + reporter.Skip(err.Error()) + return nil, nil + } + msg := &nft.MsgSend{ + ClassId: n.ClassId, + Id: n.Id, + Sender: from.AddressBech32, + Receiver: to.AddressBech32, + } + + return []simsx.SimAccount{from}, msg + } +} + +// randNFT picks a random NFT from a class belonging to the specified owner(minter). +func randNFT(ctx context.Context, r *simsx.XRand, k keeper.Keeper, minter sdk.AccAddress) (nft.NFT, error) { + c, err := randClass(ctx, r, k) + if err != nil { + return nft.NFT{}, err + } + + if ns := k.GetNFTsOfClassByOwner(ctx, c.Id, minter); len(ns) > 0 { + return ns[r.Intn(len(ns))], nil + } + + n := nft.NFT{ + ClassId: c.Id, + Id: r.StringN(10), + Uri: r.StringN(10), + } + return n, k.Mint(ctx, n, minter) +} + +// randClass picks a random Class. +func randClass(ctx context.Context, r *simsx.XRand, k keeper.Keeper) (nft.Class, error) { + if classes := k.GetClasses(ctx); len(classes) != 0 { + return *classes[r.Intn(len(classes))], nil + } + c := nft.Class{ + Id: r.StringN(10), + Name: r.StringN(10), + Symbol: r.StringN(10), + Description: r.StringN(10), + Uri: r.StringN(10), + } + return c, k.SaveClass(ctx, c) +} diff --git a/x/nft/simulation/operations.go b/x/nft/simulation/operations.go deleted file mode 100644 index f13a47c49e84..000000000000 --- a/x/nft/simulation/operations.go +++ /dev/null @@ -1,170 +0,0 @@ -package simulation - -import ( - "math/rand" - - "cosmossdk.io/x/nft" - "cosmossdk.io/x/nft/keeper" - - "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/codec" - cdctypes "github.com/cosmos/cosmos-sdk/codec/types" - simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" - sdk "github.com/cosmos/cosmos-sdk/types" - simtypes "github.com/cosmos/cosmos-sdk/types/simulation" - "github.com/cosmos/cosmos-sdk/x/simulation" -) - -const ( - // OpWeightMsgSend Simulation operation weights constants - OpWeightMsgSend = "op_weight_msg_send" - - // WeightSend nft operations weights - WeightSend = 100 -) - -var TypeMsgSend = sdk.MsgTypeURL(&nft.MsgSend{}) - -// WeightedOperations returns all the operations from the module with their respective weights -func WeightedOperations( - registry cdctypes.InterfaceRegistry, - appParams simtypes.AppParams, - _ codec.JSONCodec, - txCfg client.TxConfig, - ak nft.AccountKeeper, - bk nft.BankKeeper, - k keeper.Keeper, -) simulation.WeightedOperations { - var weightMsgSend int - - appParams.GetOrGenerate(OpWeightMsgSend, &weightMsgSend, nil, - func(_ *rand.Rand) { - weightMsgSend = WeightSend - }, - ) - - return simulation.WeightedOperations{ - simulation.NewWeightedOperation( - weightMsgSend, - SimulateMsgSend(codec.NewProtoCodec(registry), txCfg, ak, bk, k), - ), - } -} - -// SimulateMsgSend generates a MsgSend with random values. -func SimulateMsgSend( - _ *codec.ProtoCodec, - txCfg client.TxConfig, - ak nft.AccountKeeper, - bk nft.BankKeeper, - k keeper.Keeper, -) simtypes.Operation { - return func( - r *rand.Rand, app simtypes.AppEntrypoint, ctx sdk.Context, accs []simtypes.Account, chainID string, - ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { - sender, _ := simtypes.RandomAcc(r, accs) - receiver, _ := simtypes.RandomAcc(r, accs) - - if sender.Address.Equals(receiver.Address) { - return simtypes.NoOpMsg(nft.ModuleName, TypeMsgSend, "sender and receiver are same"), nil, nil - } - - senderAcc := ak.GetAccount(ctx, sender.Address) - spendableCoins := bk.SpendableCoins(ctx, sender.Address) - fees, err := simtypes.RandomFees(r, spendableCoins) - if err != nil { - return simtypes.NoOpMsg(nft.ModuleName, TypeMsgSend, err.Error()), nil, err - } - - spendLimit := spendableCoins.Sub(fees...) - if spendLimit == nil { - return simtypes.NoOpMsg(nft.ModuleName, TypeMsgSend, "spend limit is nil"), nil, nil - } - - n, err := randNFT(ctx, r, k, senderAcc.GetAddress()) - if err != nil { - return simtypes.NoOpMsg(nft.ModuleName, TypeMsgSend, err.Error()), nil, err - } - - senderStr, err := ak.AddressCodec().BytesToString(senderAcc.GetAddress().Bytes()) - if err != nil { - return simtypes.NoOpMsg(nft.ModuleName, TypeMsgSend, err.Error()), nil, err - } - - receiverStr, err := ak.AddressCodec().BytesToString(receiver.Address.Bytes()) - if err != nil { - return simtypes.NoOpMsg(nft.ModuleName, TypeMsgSend, err.Error()), nil, err - } - - msg := &nft.MsgSend{ - ClassId: n.ClassId, - Id: n.Id, - Sender: senderStr, - Receiver: receiverStr, - } - - tx, err := simtestutil.GenSignedMockTx( - r, - txCfg, - []sdk.Msg{msg}, - fees, - simtestutil.DefaultGenTxGas, - chainID, - []uint64{senderAcc.GetAccountNumber()}, - []uint64{senderAcc.GetSequence()}, - sender.PrivKey, - ) - if err != nil { - return simtypes.NoOpMsg(nft.ModuleName, TypeMsgSend, "unable to generate mock tx"), nil, err - } - - if _, _, err = app.SimDeliver(txCfg.TxEncoder(), tx); err != nil { - return simtypes.NoOpMsg(nft.ModuleName, sdk.MsgTypeURL(msg), "unable to deliver tx"), nil, err - } - - return simtypes.NewOperationMsg(msg, true, ""), nil, nil - } -} - -// randNFT picks a random NFT from a class belonging to the specified owner(minter). -func randNFT(ctx sdk.Context, r *rand.Rand, k keeper.Keeper, minter sdk.AccAddress) (nft.NFT, error) { - c, err := randClass(ctx, r, k) - if err != nil { - return nft.NFT{}, err - } - ns := k.GetNFTsOfClassByOwner(ctx, c.Id, minter) - if len(ns) > 0 { - return ns[r.Intn(len(ns))], nil - } - - n := nft.NFT{ - ClassId: c.Id, - Id: simtypes.RandStringOfLength(r, 10), - Uri: simtypes.RandStringOfLength(r, 10), - } - err = k.Mint(ctx, n, minter) - if err != nil { - return nft.NFT{}, err - } - return n, nil -} - -// randClass picks a random Class. -func randClass(ctx sdk.Context, r *rand.Rand, k keeper.Keeper) (nft.Class, error) { - classes := k.GetClasses(ctx) - if len(classes) == 0 { - c := nft.Class{ - Id: simtypes.RandStringOfLength(r, 10), - Name: simtypes.RandStringOfLength(r, 10), - Symbol: simtypes.RandStringOfLength(r, 10), - Description: simtypes.RandStringOfLength(r, 10), - Uri: simtypes.RandStringOfLength(r, 10), - } - err := k.SaveClass(ctx, c) - if err != nil { - return nft.Class{}, err - } - return c, nil - } - return *classes[r.Intn(len(classes))], nil -} diff --git a/x/params/go.mod b/x/params/go.mod index fcab30fbb022..f072f3b0256b 100644 --- a/x/params/go.mod +++ b/x/params/go.mod @@ -3,9 +3,9 @@ module cosmossdk.io/x/params go 1.23.1 require ( - cosmossdk.io/api v0.7.5 - cosmossdk.io/core v1.0.0-alpha.2 - cosmossdk.io/core/testing v0.0.0-00010101000000-000000000000 + cosmossdk.io/api v0.7.6 + cosmossdk.io/core v1.0.0-alpha.4 + cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29 cosmossdk.io/depinject v1.0.0 cosmossdk.io/errors v1.0.1 cosmossdk.io/log v1.4.1 @@ -21,17 +21,15 @@ require ( github.com/grpc-ecosystem/grpc-gateway v1.16.0 github.com/spf13/cobra v1.8.1 github.com/stretchr/testify v1.9.0 - google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 - google.golang.org/grpc v1.66.2 + google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 + google.golang.org/grpc v1.67.1 ) require ( buf.build/gen/go/cometbft/cometbft/protocolbuffers/go v1.34.2-20240701160653-fedbb9acfd2f.2 // indirect buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.34.2-20240130113600-88ef6483f90f.2 // indirect cosmossdk.io/collections v0.4.0 // indirect - cosmossdk.io/schema v0.2.0 // indirect - cosmossdk.io/x/bank v0.0.0-20240226161501-23359a0b6d91 // indirect - cosmossdk.io/x/staking v0.0.0-00010101000000-000000000000 // indirect + cosmossdk.io/schema v0.3.1-0.20240930054013-7c6e0388a3f9 // indirect cosmossdk.io/x/tx v0.13.3 // indirect filippo.io/edwards25519 v1.1.0 // indirect github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect @@ -52,7 +50,6 @@ require ( github.com/cometbft/cometbft v1.0.0-rc1.0.20240908111210-ab0be101882f // indirect github.com/cometbft/cometbft-db v0.15.0 // indirect github.com/cosmos/btcutil v1.0.5 // indirect - github.com/cosmos/cosmos-db v1.0.3-0.20240911104526-ddc3f09bfc22 // indirect github.com/cosmos/crypto v0.1.2 // indirect github.com/cosmos/go-bip39 v1.0.0 // indirect github.com/cosmos/gogogateway v1.2.0 // indirect @@ -82,8 +79,6 @@ require ( github.com/google/btree v1.1.3 // indirect github.com/google/flatbuffers v2.0.8+incompatible // indirect github.com/google/go-cmp v0.6.0 // indirect - github.com/google/orderedcode v0.0.1 // indirect - github.com/google/uuid v1.6.0 // indirect github.com/gorilla/handlers v1.5.2 // indirect github.com/gorilla/mux v1.8.1 // indirect github.com/gorilla/websocket v1.5.3 // indirect @@ -94,23 +89,20 @@ require ( github.com/hashicorp/go-metrics v0.5.3 // indirect github.com/hashicorp/go-plugin v1.6.1 // indirect github.com/hashicorp/golang-lru v1.0.2 // indirect - github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/hashicorp/yamux v0.1.1 // indirect github.com/hdevalence/ed25519consensus v0.2.0 // indirect - github.com/huandu/skiplist v1.2.0 // indirect + github.com/huandu/skiplist v1.2.1 // indirect github.com/iancoleman/strcase v0.3.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jmhodges/levigo v1.0.0 // indirect github.com/klauspost/compress v1.17.9 // indirect github.com/kr/pretty v0.3.1 // indirect github.com/kr/text v0.2.0 // indirect - github.com/lib/pq v1.10.9 // indirect github.com/linxGnu/grocksdb v1.9.3 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect - github.com/minio/highwayhash v1.0.3 // 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 @@ -121,13 +113,12 @@ require ( github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/client_golang v1.20.3 // indirect + github.com/prometheus/client_golang v1.20.4 // indirect github.com/prometheus/client_model v0.6.1 // indirect - github.com/prometheus/common v0.59.1 // indirect + github.com/prometheus/common v0.60.0 // indirect github.com/prometheus/procfs v0.15.1 // indirect github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect github.com/rogpeppe/go-internal v1.12.0 // indirect - github.com/rs/cors v1.11.0 // indirect github.com/rs/zerolog v1.33.0 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect @@ -159,7 +150,7 @@ require ( golang.org/x/text v0.18.0 // indirect golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f // indirect google.golang.org/protobuf v1.34.2 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect @@ -173,7 +164,6 @@ replace github.com/cosmos/cosmos-sdk => ../.. // TODO remove post spinning out all modules replace ( cosmossdk.io/api => ../../api - cosmossdk.io/core/testing => ../../core/testing cosmossdk.io/store => ../../store cosmossdk.io/x/bank => ../bank cosmossdk.io/x/distribution => ../distribution diff --git a/x/params/go.sum b/x/params/go.sum index a658644fd79f..048c9a1067ea 100644 --- a/x/params/go.sum +++ b/x/params/go.sum @@ -6,8 +6,10 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cosmossdk.io/collections v0.4.0 h1:PFmwj2W8szgpD5nOd8GWH6AbYNi1f2J6akWXJ7P5t9s= cosmossdk.io/collections v0.4.0/go.mod h1:oa5lUING2dP+gdDquow+QjlF45eL1t4TJDypgGd+tv0= -cosmossdk.io/core v1.0.0-alpha.2 h1:epU0Xwces4Rgl5bMhHHkXGaGDcyucNGlC/JDH+Suckg= -cosmossdk.io/core v1.0.0-alpha.2/go.mod h1:abgLjeFLhtuKIYZWSPlVUgQBrKObO7ULV35KYfexE90= +cosmossdk.io/core v1.0.0-alpha.4 h1:9iuroT9ejDYETCsGkzkvs/wAY/5UFl7nCIINFRxyMJY= +cosmossdk.io/core v1.0.0-alpha.4/go.mod h1:3u9cWq1FAVtiiCrDPpo4LhR+9V6k/ycSG4/Y/tREWCY= +cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29 h1:NxxUo0GMJUbIuVg0R70e3cbn9eFTEuMr7ev1AFvypdY= +cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29/go.mod h1:8s2tPeJtSiQuoyPmr2Ag7meikonISO4Fv4MoO8+ORrs= cosmossdk.io/depinject v1.0.0 h1:dQaTu6+O6askNXO06+jyeUAnF2/ssKwrrszP9t5q050= cosmossdk.io/depinject v1.0.0/go.mod h1:zxK/h3HgHoA/eJVtiSsoaRaRA2D5U4cJ5thIG4ssbB8= cosmossdk.io/errors v1.0.1 h1:bzu+Kcr0kS/1DuPBtUFdWjzLqyUuCiyHjyJB6srBV/0= @@ -16,16 +18,14 @@ cosmossdk.io/log v1.4.1 h1:wKdjfDRbDyZRuWa8M+9nuvpVYxrEOwbD/CA8hvhU8QM= cosmossdk.io/log v1.4.1/go.mod h1:k08v0Pyq+gCP6phvdI6RCGhLf/r425UT6Rk/m+o74rU= cosmossdk.io/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE= cosmossdk.io/math v1.3.0/go.mod h1:vnRTxewy+M7BtXBNFybkuhSH4WfedVAAnERHgVFhp3k= -cosmossdk.io/schema v0.2.0 h1:UH5CR1DqUq8yP+5Np8PbvG4YX0zAUsTN2Qk6yThmfMk= -cosmossdk.io/schema v0.2.0/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= +cosmossdk.io/schema v0.3.1-0.20240930054013-7c6e0388a3f9 h1:DmOoS/1PeY6Ih0hAVlJ69kLMUrLV+TCbfICrZtB1vdU= +cosmossdk.io/schema v0.3.1-0.20240930054013-7c6e0388a3f9/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMbk2FiG/kXiLl8BRyzTWDw7gX/Hz7Dd5eDMs= github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4/go.mod h1:hN7oaIRCjzsZ2dE+yG5k+rsdt3qcwykqK6HVGcKwsw4= github.com/99designs/keyring v1.2.2 h1:pZd3neh/EmUzWONb35LxQfvuY7kiSXAq3HQd97+XBn0= github.com/99designs/keyring v1.2.2/go.mod h1:wes/FrByc8j7lFOAGLGSNEg8f/PaI3cgTBqhFkHUrPk= -github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0= -github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/DataDog/datadog-go v4.8.3+incompatible h1:fNGaYSuObuQb5nzeTQqowRAd9bpDIRRV4/gUtIBjh8Q= @@ -34,12 +34,8 @@ github.com/DataDog/zstd v1.5.5 h1:oWf5W7GtOLgp6bciQYDmhHHjdhYkALu6S/5Ni9ZgSvQ= github.com/DataDog/zstd v1.5.5/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= -github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw= -github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk= github.com/VividCortex/gohistogram v1.0.0 h1:6+hBz+qvs0JOrrNhhmR7lFxo5sINxBCGXrdtl/UvroE= github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= -github.com/adlio/schema v1.3.6 h1:k1/zc2jNfeiZBA5aFTRy37jlBIuCkXCm0XmvpzCKI9I= -github.com/adlio/schema v1.3.6/go.mod h1:qkxwLgPBd1FgLRHYVCmQT/rrBr3JH38J9LjmVzWNudg= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= @@ -60,8 +56,6 @@ github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOF github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/bufbuild/protocompile v0.4.0 h1:LbFKd2XowZvQ/kajzguUp2DC9UEIQhIq77fZZlaQsNA= github.com/bufbuild/protocompile v0.4.0/go.mod h1:3v93+mbWn/v3xzN+31nwkJfrEpAUwp+BagBSZWx+TP8= -github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4= -github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= @@ -99,8 +93,6 @@ github.com/cometbft/cometbft-db v0.15.0 h1:VLtsRt8udD4jHCyjvrsTBpgz83qne5hnL245A github.com/cometbft/cometbft-db v0.15.0/go.mod h1:EBrFs1GDRiTqrWXYi4v90Awf/gcdD5ExzdPbg4X8+mk= github.com/cometbft/cometbft/api v1.0.0-rc.1 h1:GtdXwDGlqwHYs16A4egjwylfYOMYyEacLBrs3Zvpt7g= github.com/cometbft/cometbft/api v1.0.0-rc.1/go.mod h1:NDFKiBBD8HJC6QQLAoUI99YhsiRZtg2+FJWfk6A6m6o= -github.com/containerd/continuity v0.3.0 h1:nisirsYROK15TAMVukJOUyGJjz4BNQJBVsNvAXZJ/eg= -github.com/containerd/continuity v0.3.0/go.mod h1:wJEAIwKOm/pBZuBd0JmeTvnLquTB1Ag8espWhkykbPM= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/cosmos/btcutil v1.0.5 h1:t+ZFcX77LpKtDBhjucvnOH8C2l2ioGsBNEQ3jef8xFk= github.com/cosmos/btcutil v1.0.5/go.mod h1:IyB7iuqZMJlthe2tkIFL33xPyzbFYP0XVdS8P5lUPis= @@ -141,10 +133,6 @@ github.com/dgraph-io/ristretto v0.1.2-0.20240116140435-c67e07994f91 h1:Pux6+xANi github.com/dgraph-io/ristretto v0.1.2-0.20240116140435-c67e07994f91/go.mod h1:swkazRqnUf1N62d0Nutz7KIj2UKqsm/H8tD0nBJAXqM= github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 h1:fAjc9m62+UWV/WAFKLNi6ZS0675eEUC9y3AlwSbQu1Y= github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= -github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= -github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= -github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= -github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/dvsekhvalnov/jose2go v1.6.0 h1:Y9gnSnP4qEI0+/uQkHvFXeD2PLPJeXEL+ySMEA2EjTY= @@ -292,8 +280,8 @@ github.com/hdevalence/ed25519consensus v0.2.0/go.mod h1:w3BHWjwJbFU29IRHL1Iqkw3s github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/huandu/go-assert v1.1.5 h1:fjemmA7sSfYHJD7CUqs9qTwwfdNAx7/j2/ZlHXzNB3c= github.com/huandu/go-assert v1.1.5/go.mod h1:yOLvuqZwmcHIC5rIzrBhT7D3Q9c3GFnd0JrPVhn/06U= -github.com/huandu/skiplist v1.2.0 h1:gox56QD77HzSC0w+Ws3MH3iie755GBJU1OER3h5VsYw= -github.com/huandu/skiplist v1.2.0/go.mod h1:7v3iFjLcSAzO4fN5B8dvebvo/qsfumiLiDXMrPiHF9w= +github.com/huandu/skiplist v1.2.1 h1:dTi93MgjwErA/8idWTzIw4Y1kZsMWx35fmI2c8Rij7w= +github.com/huandu/skiplist v1.2.1/go.mod h1:7v3iFjLcSAzO4fN5B8dvebvo/qsfumiLiDXMrPiHF9w= github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI= github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= @@ -320,8 +308,6 @@ 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= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= -github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/linxGnu/grocksdb v1.9.3 h1:s1cbPcOd0cU2SKXRG1nEqCOWYAELQjdqg3RVI2MH9ik= @@ -374,15 +360,7 @@ github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAl github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= github.com/onsi/gomega v1.28.1 h1:MijcGUbfYuznzK/5R4CPNoUP/9Xvuo20sXfEm6XxoTA= github.com/onsi/gomega v1.28.1/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ= -github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= -github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= -github.com/opencontainers/image-spec v1.1.0-rc5 h1:Ygwkfw9bpDvs+c9E34SdgGOj41dX/cbdlwvlWt0pnFI= -github.com/opencontainers/image-spec v1.1.0-rc5/go.mod h1:X4pATf0uXsnn3g5aiGIsVnJBR4mxhKzfwmvK/B2NTm8= -github.com/opencontainers/runc v1.1.12 h1:BOIssBaW1La0/qbNZHXOOa71dZfZEQOzW7dqQf3phss= -github.com/opencontainers/runc v1.1.12/go.mod h1:S+lQwSfncpBha7XTy/5lBwWgm5+y5Ma/O44Ekby9FK8= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= -github.com/ory/dockertest v3.3.5+incompatible h1:iLLK6SQwIhcbrG783Dghaaa3WPzGc+4Emza6EbVUUGA= -github.com/ory/dockertest v3.3.5+incompatible/go.mod h1:1vX4m9wsvi00u5bseYwXaSnhNrne+V0E6LAcBILJdPs= github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M= @@ -402,8 +380,8 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= -github.com/prometheus/client_golang v1.20.3 h1:oPksm4K8B+Vt35tUhw6GbSNSgVlVSBH0qELP/7u83l4= -github.com/prometheus/client_golang v1.20.3/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_golang v1.20.4 h1:Tgh3Yr67PaOv/uTqloMsCEdeuFTatm5zIq5+qNN23vI= +github.com/prometheus/client_golang v1.20.4/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -412,8 +390,8 @@ github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= -github.com/prometheus/common v0.59.1 h1:LXb1quJHWm1P6wq/U824uxYi4Sg0oGvNeUm1z5dJoX0= -github.com/prometheus/common v0.59.1/go.mod h1:GpWM7dewqmVYcd7SmRaiWVe9SSqjf0UrwnYnpEZNuT0= +github.com/prometheus/common v0.60.0 h1:+V9PAREWNvJMAuJ1x1BaWl9dewMW4YrHZQbx0sJNllA= +github.com/prometheus/common v0.60.0/go.mod h1:h0LYf1R1deLSKtD4Vdg8gy4RuOvENW2J/h19V5NADQw= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/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= @@ -439,8 +417,6 @@ github.com/sasha-s/go-deadlock v0.3.5 h1:tNCOEEDG6tBqrNDOX35j/7hL5FcFViG6awUGROb github.com/sasha-s/go-deadlock v0.3.5/go.mod h1:bugP6EGbdGYObIlx7pUZtWqlvo8k9H6vCBBsiChJQ5U= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= -github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= -github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= @@ -592,7 +568,6 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= @@ -636,10 +611,10 @@ google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEY google.golang.org/genproto v0.0.0-20220314164441-57ef72a4c106/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E= google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de h1:F6qOa9AZTYJXOUEr4jDysRDLrm4PHePlge4v4TGAlxY= google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:VUhTRKeHn9wwcdrk73nvdC9gF178Tzhmt/qyaFcPLSo= -google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 h1:+rdxYoE3E5htTEWIe15GlN6IfvbURM//Jt0mmkmm6ZU= -google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117/go.mod h1:OimBR/bc1wPO9iV4NC2bpyjy3VnAwZh5EBPQdtaE5oo= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:pPJltXNxVzT4pK9yD8vR9X75DaWYYmLGMsEvBfFQZzQ= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= +google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 h1:wKguEg1hsxI2/L3hUYrpo1RVi48K+uTyzKqprwLXsb8= +google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142/go.mod h1:d6be+8HhtEtucleCbxpPW9PA9XwISACu8nvpPqF0BVo= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f h1:cUMEy+8oS78BWIH9OWazBkzbr090Od9tWBNtZHkOhf0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= @@ -650,8 +625,8 @@ google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= -google.golang.org/grpc v1.66.2 h1:3QdXkuq3Bkh7w+ywLdLvM56cmGvQHUMZpiCzt6Rqaoo= -google.golang.org/grpc v1.66.2/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y= +google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E= +google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= 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= diff --git a/x/params/keeper/keeper_test.go b/x/params/keeper/keeper_test.go index d82db839dd35..25b7609fed08 100644 --- a/x/params/keeper/keeper_test.go +++ b/x/params/keeper/keeper_test.go @@ -88,13 +88,11 @@ func TestKeeper(t *testing.T) { // Set params for i, kv := range kvs { - kv := kv require.NotPanics(t, func() { space.Set(ctx, []byte(kv.key), kv.param) }, "space.Set panics, tc #%d", i) } // Test space.Get for i, kv := range kvs { - i, kv := i, kv var param int64 require.NotPanics(t, func() { space.Get(ctx, []byte(kv.key), ¶m) }, "space.Get panics, tc #%d", i) require.Equal(t, kv.param, param, "stored param not equal, tc #%d", i) @@ -121,20 +119,17 @@ func TestKeeper(t *testing.T) { // Test invalid space.Get for i, kv := range kvs { - kv := kv var param bool require.Panics(t, func() { space.Get(ctx, []byte(kv.key), ¶m) }, "invalid space.Get not panics, tc #%d", i) } // Test invalid space.Set for i, kv := range kvs { - kv := kv require.Panics(t, func() { space.Set(ctx, []byte(kv.key), true) }, "invalid space.Set not panics, tc #%d", i) } // Test GetSubspace for i, kv := range kvs { - i, kv := i, kv var gparam, param int64 gspace, ok := keeper.GetSubspace("test") require.True(t, ok, "cannot retrieve subspace, tc #%d", i) @@ -219,7 +214,6 @@ func TestSubspace(t *testing.T) { // Test space.Set, space.Modified for i, kv := range kvs { - i, kv := i, kv require.False(t, space.Modified(ctx, []byte(kv.key)), "space.Modified returns true before setting, tc #%d", i) require.NotPanics(t, func() { space.Set(ctx, []byte(kv.key), kv.param) }, "space.Set panics, tc #%d", i) require.True(t, space.Modified(ctx, []byte(kv.key)), "space.Modified returns false after setting, tc #%d", i) @@ -227,7 +221,6 @@ func TestSubspace(t *testing.T) { // Test space.Get, space.GetIfExists for i, kv := range kvs { - i, kv := i, kv require.NotPanics(t, func() { space.GetIfExists(ctx, []byte("invalid"), kv.ptr) }, "space.GetIfExists panics when no value exists, tc #%d", i) require.Equal(t, kv.zero, indirect(kv.ptr), "space.GetIfExists unmarshalls when no value exists, tc #%d", i) require.Panics(t, func() { space.Get(ctx, []byte("invalid"), kv.ptr) }, "invalid space.Get not panics when no value exists, tc #%d", i) diff --git a/x/params/module.go b/x/params/module.go index 006afd56b33c..cc531691e9cc 100644 --- a/x/params/module.go +++ b/x/params/module.go @@ -79,10 +79,5 @@ func (am AppModule) RegisterServices(registrar grpc.ServiceRegistrar) error { // RegisterStoreDecoder doesn't register any type. func (AppModule) RegisterStoreDecoder(sdr simtypes.StoreDecoderRegistry) {} -// WeightedOperations returns the all the gov module operations with their respective weights. -func (am AppModule) WeightedOperations(_ module.SimulationState) []simtypes.WeightedOperation { - return nil -} - // ConsensusVersion implements HasConsensusVersion func (AppModule) ConsensusVersion() uint64 { return ConsensusVersion } diff --git a/x/params/simulation/operations.go b/x/params/simulation/operations.go deleted file mode 100644 index c8e6b7de3f63..000000000000 --- a/x/params/simulation/operations.go +++ /dev/null @@ -1,54 +0,0 @@ -package simulation - -import ( - "fmt" - "math/rand" - - "cosmossdk.io/x/params/types/proposal" - - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/types/simulation" -) - -func min(a, b int) int { - if a <= b { - return a - } - return b -} - -// SimulateParamChangeProposalContent returns random parameter change content. -// It will generate a ParameterChangeProposal object with anywhere between 1 and -// the total amount of defined parameters changes, all of which have random valid values. -func SimulateParamChangeProposalContent(paramChangePool []simulation.LegacyParamChange) simulation.ContentSimulatorFn { //nolint:staticcheck // used for legacy testing - numProposals := 0 - // Bound the maximum number of simultaneous parameter changes - maxSimultaneousParamChanges := min(len(paramChangePool), 1000) - if maxSimultaneousParamChanges == 0 { - panic("param changes array is empty") - } - - return func(r *rand.Rand, _ sdk.Context, _ []simulation.Account) simulation.Content { //nolint:staticcheck // used for legacy testing - numChanges := simulation.RandIntBetween(r, 1, maxSimultaneousParamChanges) - paramChanges := make([]proposal.ParamChange, numChanges) - - // perm here takes at most len(paramChangePool) calls to random - paramChoices := r.Perm(len(paramChangePool)) - - for i := 0; i < numChanges; i++ { - spc := paramChangePool[paramChoices[i]] - // add a new distinct parameter to the set of changes - paramChanges[i] = proposal.NewParamChange(spc.Subspace(), spc.Key(), spc.SimValue()(r)) - } - - title := fmt.Sprintf("title from SimulateParamChangeProposalContent-%d", numProposals) - desc := fmt.Sprintf("desc from SimulateParamChangeProposalContent-%d. Random short desc: %s", - numProposals, simulation.RandStringOfLength(r, 20)) - numProposals++ - return proposal.NewParameterChangeProposal( - title, // title - desc, // description - paramChanges, // set of changes - ) - } -} diff --git a/x/params/simulation/operations_test.go b/x/params/simulation/operations_test.go deleted file mode 100644 index 65623381cf4a..000000000000 --- a/x/params/simulation/operations_test.go +++ /dev/null @@ -1,65 +0,0 @@ -package simulation_test - -import ( - "fmt" - "math/rand" - "testing" - - "github.com/stretchr/testify/require" - - "cosmossdk.io/x/params/simulation" - "cosmossdk.io/x/params/types/proposal" - - sdk "github.com/cosmos/cosmos-sdk/types" - simtypes "github.com/cosmos/cosmos-sdk/types/simulation" -) - -type MockParamChange struct { - n int -} - -func (pc MockParamChange) Subspace() string { - return fmt.Sprintf("test-Subspace%d", pc.n) -} - -func (pc MockParamChange) Key() string { - return fmt.Sprintf("test-Key%d", pc.n) -} - -func (pc MockParamChange) ComposedKey() string { - return fmt.Sprintf("test-ComposedKey%d", pc.n) -} - -func (pc MockParamChange) SimValue() simtypes.SimValFn { - return func(r *rand.Rand) string { - return fmt.Sprintf("test-value %d%d ", pc.n, int64(simtypes.RandIntBetween(r, 10, 1000))) - } -} - -// make sure that the MockParamChange satisfied the ParamChange interface -var _ simtypes.LegacyParamChange = MockParamChange{} - -func TestSimulateParamChangeProposalContent(t *testing.T) { - s := rand.NewSource(1) - r := rand.New(s) - - ctx := sdk.NewContext(nil, true, nil) - accounts := simtypes.RandomAccounts(r, 3) - paramChangePool := []simtypes.LegacyParamChange{MockParamChange{1}, MockParamChange{2}, MockParamChange{3}} - - // execute operation - op := simulation.SimulateParamChangeProposalContent(paramChangePool) - content := op(r, ctx, accounts) - - require.Equal(t, "desc from SimulateParamChangeProposalContent-0. Random short desc: IivHSlcxgdXhhuTSkuxK", content.GetDescription()) - require.Equal(t, "title from SimulateParamChangeProposalContent-0", content.GetTitle()) - require.Equal(t, "params", content.ProposalRoute()) - require.Equal(t, "ParameterChange", content.ProposalType()) - - pcp, ok := content.(*proposal.ParameterChangeProposal) - require.True(t, ok) - - require.Equal(t, "test-Key2", pcp.Changes[0].GetKey()) - require.Equal(t, "test-value 2791 ", pcp.Changes[0].GetValue()) - require.Equal(t, "test-Subspace2", pcp.Changes[0].GetSubspace()) -} diff --git a/x/params/simulation/proposals.go b/x/params/simulation/proposals.go deleted file mode 100644 index 8dc636fa05c2..000000000000 --- a/x/params/simulation/proposals.go +++ /dev/null @@ -1,25 +0,0 @@ -package simulation - -import ( - simtypes "github.com/cosmos/cosmos-sdk/types/simulation" - "github.com/cosmos/cosmos-sdk/x/simulation" -) - -const ( - // OpWeightSubmitParamChangeProposal app params key for param change proposal - OpWeightSubmitParamChangeProposal = "op_weight_submit_param_change_proposal" - DefaultWeightParamChangeProposal = 5 -) - -// ProposalContents defines the module weighted proposals' contents -// -//nolint:staticcheck // used for legacy testing -func ProposalContents(paramChanges []simtypes.LegacyParamChange) []simtypes.WeightedProposalContent { - return []simtypes.WeightedProposalContent{ - simulation.NewWeightedProposalContent( - OpWeightSubmitParamChangeProposal, - DefaultWeightParamChangeProposal, - SimulateParamChangeProposalContent(paramChanges), - ), - } -} diff --git a/x/params/simulation/proposals_test.go b/x/params/simulation/proposals_test.go deleted file mode 100644 index 63417433492d..000000000000 --- a/x/params/simulation/proposals_test.go +++ /dev/null @@ -1,50 +0,0 @@ -package simulation_test - -import ( - "math/rand" - "testing" - - "github.com/stretchr/testify/require" - - "cosmossdk.io/x/params/simulation" - "cosmossdk.io/x/params/types/proposal" - - sdk "github.com/cosmos/cosmos-sdk/types" - simtypes "github.com/cosmos/cosmos-sdk/types/simulation" -) - -func TestProposalContents(t *testing.T) { - // initialize parameters - s := rand.NewSource(1) - r := rand.New(s) - - ctx := sdk.NewContext(nil, true, nil) - accounts := simtypes.RandomAccounts(r, 3) - - paramChangePool := []simtypes.LegacyParamChange{MockParamChange{1}, MockParamChange{2}, MockParamChange{3}} - - // execute ProposalContents function - weightedProposalContent := simulation.ProposalContents(paramChangePool) - require.Len(t, weightedProposalContent, 1) - - w0 := weightedProposalContent[0] - - // tests w0 interface: - require.Equal(t, simulation.OpWeightSubmitParamChangeProposal, w0.AppParamsKey()) - require.Equal(t, simulation.DefaultWeightParamChangeProposal, w0.DefaultWeight()) - - content := w0.ContentSimulatorFn()(r, ctx, accounts) - - require.Equal(t, "desc from SimulateParamChangeProposalContent-0. Random short desc: IivHSlcxgdXhhuTSkuxK", content.GetDescription()) - require.Equal(t, "title from SimulateParamChangeProposalContent-0", content.GetTitle()) - require.Equal(t, "params", content.ProposalRoute()) - require.Equal(t, "ParameterChange", content.ProposalType()) - - pcp, ok := content.(*proposal.ParameterChangeProposal) - require.True(t, ok) - - require.Len(t, pcp.Changes, 1) - require.Equal(t, "test-Key2", pcp.Changes[0].GetKey()) - require.Equal(t, "test-value 2791 ", pcp.Changes[0].GetValue()) - require.Equal(t, "test-Subspace2", pcp.Changes[0].GetSubspace()) -} diff --git a/x/params/types/subspace_test.go b/x/params/types/subspace_test.go index 947c86446bc8..651d868ec18f 100644 --- a/x/params/types/subspace_test.go +++ b/x/params/types/subspace_test.go @@ -236,7 +236,6 @@ func (suite *SubspaceTestSuite) TestSetParamSet() { } for _, tc := range testCases { - tc := tc suite.Run(tc.name, func() { suite.Require().Panics(func() { suite.ss.SetParamSet(suite.ctx, tc.ps) diff --git a/x/protocolpool/depinject.go b/x/protocolpool/depinject.go index ff07c3319639..a2dc1c950c63 100644 --- a/x/protocolpool/depinject.go +++ b/x/protocolpool/depinject.go @@ -10,6 +10,7 @@ import ( "cosmossdk.io/x/protocolpool/types" "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/simsx" "github.com/cosmos/cosmos-sdk/types/module" simtypes "github.com/cosmos/cosmos-sdk/types/simulation" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" @@ -79,15 +80,11 @@ func (AppModule) GenerateGenesisState(simState *module.SimulationState) { func (am AppModule) RegisterStoreDecoder(sdr simtypes.StoreDecoderRegistry) { } -// ProposalMsgs returns all the protocolpool msgs used to simulate governance proposals. -func (AppModule) ProposalMsgs(simState module.SimulationState) []simtypes.WeightedProposalMsg { - return simulation.ProposalMsgs() +// ProposalMsgsX returns all the protocolpool msgs used to simulate governance proposals. +func (am AppModule) ProposalMsgsX(weight simsx.WeightSource, reg simsx.Registry) { + reg.Add(weight.Get("msg_community_pool_spend", 50), simulation.MsgCommunityPoolSpendFactory()) } -// WeightedOperations returns the all the protocolpool module operations with their respective weights. -func (am AppModule) WeightedOperations(simState module.SimulationState) []simtypes.WeightedOperation { - return simulation.WeightedOperations( - simState.AppParams, simState.Cdc, simState.TxConfig, - am.accountKeeper, am.bankKeeper, am.keeper, - ) +func (am AppModule) WeightedOperationsX(weight simsx.WeightSource, reg simsx.Registry) { + reg.Add(weight.Get("msg_fund_community_pool", 50), simulation.MsgFundCommunityPoolFactory()) } diff --git a/x/protocolpool/go.mod b/x/protocolpool/go.mod index 75d14c4056d1..5454bc67d0dd 100644 --- a/x/protocolpool/go.mod +++ b/x/protocolpool/go.mod @@ -3,10 +3,10 @@ module cosmossdk.io/x/protocolpool go 1.23.1 require ( - cosmossdk.io/api v0.7.5 + cosmossdk.io/api v0.7.6 cosmossdk.io/collections v0.4.0 - cosmossdk.io/core v1.0.0-alpha.2 - cosmossdk.io/core/testing v0.0.0-00010101000000-000000000000 + cosmossdk.io/core v1.0.0-alpha.4 + cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29 cosmossdk.io/depinject v1.0.0 cosmossdk.io/errors v1.0.1 cosmossdk.io/math v1.3.0 @@ -18,17 +18,16 @@ require ( github.com/golang/protobuf v1.5.4 github.com/grpc-ecosystem/grpc-gateway v1.16.0 github.com/stretchr/testify v1.9.0 - google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 - google.golang.org/grpc v1.66.2 + google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 + google.golang.org/grpc v1.67.1 google.golang.org/protobuf v1.34.2 - gotest.tools/v3 v3.5.1 ) require ( buf.build/gen/go/cometbft/cometbft/protocolbuffers/go v1.34.2-20240701160653-fedbb9acfd2f.2 // indirect buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.34.2-20240130113600-88ef6483f90f.2 // indirect cosmossdk.io/log v1.4.1 // indirect - cosmossdk.io/schema v0.2.0 // indirect + cosmossdk.io/schema v0.3.1-0.20240930054013-7c6e0388a3f9 // indirect cosmossdk.io/x/bank v0.0.0-20240226161501-23359a0b6d91 // indirect cosmossdk.io/x/staking v0.0.0-00010101000000-000000000000 // indirect cosmossdk.io/x/tx v0.13.3 // indirect @@ -98,7 +97,7 @@ require ( github.com/hashicorp/hcl v1.0.0 // indirect github.com/hashicorp/yamux v0.1.1 // indirect github.com/hdevalence/ed25519consensus v0.2.0 // indirect - github.com/huandu/skiplist v1.2.0 // indirect + github.com/huandu/skiplist v1.2.1 // indirect github.com/iancoleman/strcase v0.3.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jmhodges/levigo v1.0.0 // indirect @@ -121,9 +120,9 @@ require ( github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/client_golang v1.20.3 // indirect + github.com/prometheus/client_golang v1.20.4 // indirect github.com/prometheus/client_model v0.6.1 // indirect - github.com/prometheus/common v0.59.1 // indirect + github.com/prometheus/common v0.60.0 // indirect github.com/prometheus/procfs v0.15.1 // indirect github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect github.com/rogpeppe/go-internal v1.12.0 // indirect @@ -160,9 +159,10 @@ require ( golang.org/x/text v0.18.0 // indirect golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect + gotest.tools/v3 v3.5.1 // indirect pgregory.net/rapid v1.1.0 // indirect sigs.k8s.io/yaml v1.4.0 // indirect ) @@ -172,7 +172,6 @@ replace github.com/cosmos/cosmos-sdk => ../../. // TODO remove post spinning out all modules replace ( cosmossdk.io/api => ../../api - cosmossdk.io/core/testing => ../../core/testing cosmossdk.io/store => ../../store cosmossdk.io/x/bank => ../bank cosmossdk.io/x/staking => ../staking diff --git a/x/protocolpool/go.sum b/x/protocolpool/go.sum index a658644fd79f..c9df997e10ec 100644 --- a/x/protocolpool/go.sum +++ b/x/protocolpool/go.sum @@ -6,8 +6,10 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cosmossdk.io/collections v0.4.0 h1:PFmwj2W8szgpD5nOd8GWH6AbYNi1f2J6akWXJ7P5t9s= cosmossdk.io/collections v0.4.0/go.mod h1:oa5lUING2dP+gdDquow+QjlF45eL1t4TJDypgGd+tv0= -cosmossdk.io/core v1.0.0-alpha.2 h1:epU0Xwces4Rgl5bMhHHkXGaGDcyucNGlC/JDH+Suckg= -cosmossdk.io/core v1.0.0-alpha.2/go.mod h1:abgLjeFLhtuKIYZWSPlVUgQBrKObO7ULV35KYfexE90= +cosmossdk.io/core v1.0.0-alpha.4 h1:9iuroT9ejDYETCsGkzkvs/wAY/5UFl7nCIINFRxyMJY= +cosmossdk.io/core v1.0.0-alpha.4/go.mod h1:3u9cWq1FAVtiiCrDPpo4LhR+9V6k/ycSG4/Y/tREWCY= +cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29 h1:NxxUo0GMJUbIuVg0R70e3cbn9eFTEuMr7ev1AFvypdY= +cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29/go.mod h1:8s2tPeJtSiQuoyPmr2Ag7meikonISO4Fv4MoO8+ORrs= cosmossdk.io/depinject v1.0.0 h1:dQaTu6+O6askNXO06+jyeUAnF2/ssKwrrszP9t5q050= cosmossdk.io/depinject v1.0.0/go.mod h1:zxK/h3HgHoA/eJVtiSsoaRaRA2D5U4cJ5thIG4ssbB8= cosmossdk.io/errors v1.0.1 h1:bzu+Kcr0kS/1DuPBtUFdWjzLqyUuCiyHjyJB6srBV/0= @@ -16,8 +18,8 @@ cosmossdk.io/log v1.4.1 h1:wKdjfDRbDyZRuWa8M+9nuvpVYxrEOwbD/CA8hvhU8QM= cosmossdk.io/log v1.4.1/go.mod h1:k08v0Pyq+gCP6phvdI6RCGhLf/r425UT6Rk/m+o74rU= cosmossdk.io/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE= cosmossdk.io/math v1.3.0/go.mod h1:vnRTxewy+M7BtXBNFybkuhSH4WfedVAAnERHgVFhp3k= -cosmossdk.io/schema v0.2.0 h1:UH5CR1DqUq8yP+5Np8PbvG4YX0zAUsTN2Qk6yThmfMk= -cosmossdk.io/schema v0.2.0/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= +cosmossdk.io/schema v0.3.1-0.20240930054013-7c6e0388a3f9 h1:DmOoS/1PeY6Ih0hAVlJ69kLMUrLV+TCbfICrZtB1vdU= +cosmossdk.io/schema v0.3.1-0.20240930054013-7c6e0388a3f9/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMbk2FiG/kXiLl8BRyzTWDw7gX/Hz7Dd5eDMs= @@ -292,8 +294,8 @@ github.com/hdevalence/ed25519consensus v0.2.0/go.mod h1:w3BHWjwJbFU29IRHL1Iqkw3s github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/huandu/go-assert v1.1.5 h1:fjemmA7sSfYHJD7CUqs9qTwwfdNAx7/j2/ZlHXzNB3c= github.com/huandu/go-assert v1.1.5/go.mod h1:yOLvuqZwmcHIC5rIzrBhT7D3Q9c3GFnd0JrPVhn/06U= -github.com/huandu/skiplist v1.2.0 h1:gox56QD77HzSC0w+Ws3MH3iie755GBJU1OER3h5VsYw= -github.com/huandu/skiplist v1.2.0/go.mod h1:7v3iFjLcSAzO4fN5B8dvebvo/qsfumiLiDXMrPiHF9w= +github.com/huandu/skiplist v1.2.1 h1:dTi93MgjwErA/8idWTzIw4Y1kZsMWx35fmI2c8Rij7w= +github.com/huandu/skiplist v1.2.1/go.mod h1:7v3iFjLcSAzO4fN5B8dvebvo/qsfumiLiDXMrPiHF9w= github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI= github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= @@ -402,8 +404,8 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= -github.com/prometheus/client_golang v1.20.3 h1:oPksm4K8B+Vt35tUhw6GbSNSgVlVSBH0qELP/7u83l4= -github.com/prometheus/client_golang v1.20.3/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_golang v1.20.4 h1:Tgh3Yr67PaOv/uTqloMsCEdeuFTatm5zIq5+qNN23vI= +github.com/prometheus/client_golang v1.20.4/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -412,8 +414,8 @@ github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= -github.com/prometheus/common v0.59.1 h1:LXb1quJHWm1P6wq/U824uxYi4Sg0oGvNeUm1z5dJoX0= -github.com/prometheus/common v0.59.1/go.mod h1:GpWM7dewqmVYcd7SmRaiWVe9SSqjf0UrwnYnpEZNuT0= +github.com/prometheus/common v0.60.0 h1:+V9PAREWNvJMAuJ1x1BaWl9dewMW4YrHZQbx0sJNllA= +github.com/prometheus/common v0.60.0/go.mod h1:h0LYf1R1deLSKtD4Vdg8gy4RuOvENW2J/h19V5NADQw= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/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= @@ -636,10 +638,10 @@ google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEY google.golang.org/genproto v0.0.0-20220314164441-57ef72a4c106/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E= google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de h1:F6qOa9AZTYJXOUEr4jDysRDLrm4PHePlge4v4TGAlxY= google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:VUhTRKeHn9wwcdrk73nvdC9gF178Tzhmt/qyaFcPLSo= -google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 h1:+rdxYoE3E5htTEWIe15GlN6IfvbURM//Jt0mmkmm6ZU= -google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117/go.mod h1:OimBR/bc1wPO9iV4NC2bpyjy3VnAwZh5EBPQdtaE5oo= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:pPJltXNxVzT4pK9yD8vR9X75DaWYYmLGMsEvBfFQZzQ= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= +google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 h1:wKguEg1hsxI2/L3hUYrpo1RVi48K+uTyzKqprwLXsb8= +google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142/go.mod h1:d6be+8HhtEtucleCbxpPW9PA9XwISACu8nvpPqF0BVo= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f h1:cUMEy+8oS78BWIH9OWazBkzbr090Od9tWBNtZHkOhf0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= @@ -650,8 +652,8 @@ google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= -google.golang.org/grpc v1.66.2 h1:3QdXkuq3Bkh7w+ywLdLvM56cmGvQHUMZpiCzt6Rqaoo= -google.golang.org/grpc v1.66.2/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y= +google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E= +google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= 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= diff --git a/x/protocolpool/keeper/keeper.go b/x/protocolpool/keeper/keeper.go index f0d6cff755a7..8017714a6a84 100644 --- a/x/protocolpool/keeper/keeper.go +++ b/x/protocolpool/keeper/keeper.go @@ -14,6 +14,7 @@ import ( "cosmossdk.io/x/protocolpool/types" "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/telemetry" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" ) @@ -507,5 +508,8 @@ func (k Keeper) validateContinuousFund(ctx context.Context, msg types.MsgCreateC } func (k Keeper) BeginBlocker(ctx context.Context) error { + start := telemetry.Now() + defer telemetry.ModuleMeasureSince(types.ModuleName, start, telemetry.MetricKeyBeginBlocker) + return k.SetToDistribute(ctx) } diff --git a/x/protocolpool/simulation/msg_factory.go b/x/protocolpool/simulation/msg_factory.go new file mode 100644 index 000000000000..ace70ea2bb81 --- /dev/null +++ b/x/protocolpool/simulation/msg_factory.go @@ -0,0 +1,37 @@ +package simulation + +import ( + "context" + + "cosmossdk.io/x/protocolpool/types" + + "github.com/cosmos/cosmos-sdk/simsx" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +func MsgFundCommunityPoolFactory() simsx.SimMsgFactoryFn[*types.MsgFundCommunityPool] { + return func(_ context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter) ([]simsx.SimAccount, *types.MsgFundCommunityPool) { + funder := testData.AnyAccount(reporter, simsx.WithSpendableBalance()) + fundAmount := funder.LiquidBalance().RandSubsetCoins(reporter) + msg := types.NewMsgFundCommunityPool(fundAmount, funder.AddressBech32) + return []simsx.SimAccount{funder}, msg + } +} + +// MsgCommunityPoolSpendFactory creates a gov proposal to send tokens from the community pool to a random account +func MsgCommunityPoolSpendFactory() simsx.SimMsgFactoryFn[*types.MsgCommunityPoolSpend] { + return func(_ context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter) ([]simsx.SimAccount, *types.MsgCommunityPoolSpend) { + return nil, &types.MsgCommunityPoolSpend{ + Authority: testData.ModuleAccountAddress(reporter, "gov"), + Recipient: testData.AnyAccount(reporter).AddressBech32, + Amount: must(sdk.ParseCoinsNormalized("100stake,2testtoken")), + } + } +} + +func must[T any](r T, err error) T { + if err != nil { + panic(err) + } + return r +} diff --git a/x/protocolpool/simulation/operations.go b/x/protocolpool/simulation/operations.go deleted file mode 100644 index 2118b4488a50..000000000000 --- a/x/protocolpool/simulation/operations.go +++ /dev/null @@ -1,94 +0,0 @@ -package simulation - -import ( - "math/rand" - - "cosmossdk.io/x/protocolpool/keeper" - "cosmossdk.io/x/protocolpool/types" - - "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/codec" - sdk "github.com/cosmos/cosmos-sdk/types" - simtypes "github.com/cosmos/cosmos-sdk/types/simulation" - "github.com/cosmos/cosmos-sdk/x/simulation" -) - -// Simulation operation weights constants -const ( - OpWeightMsgFundCommunityPool = "op_weight_msg_fund_community_pool" - - DefaultWeightMsgFundCommunityPool int = 50 -) - -// WeightedOperations returns all the operations from the module with their respective weights -func WeightedOperations( - appParams simtypes.AppParams, - _ codec.JSONCodec, - txConfig client.TxConfig, - ak types.AccountKeeper, - bk types.BankKeeper, - k keeper.Keeper, -) simulation.WeightedOperations { - var weightMsgFundCommunityPool int - appParams.GetOrGenerate(OpWeightMsgFundCommunityPool, &weightMsgFundCommunityPool, nil, func(_ *rand.Rand) { - weightMsgFundCommunityPool = DefaultWeightMsgFundCommunityPool - }) - - return simulation.WeightedOperations{ - simulation.NewWeightedOperation( - weightMsgFundCommunityPool, - SimulateMsgFundCommunityPool(txConfig, ak, bk, k), - ), - } -} - -// SimulateMsgFundCommunityPool simulates MsgFundCommunityPool execution where -// a random account sends a random amount of its funds to the community pool. -func SimulateMsgFundCommunityPool(txConfig client.TxConfig, ak types.AccountKeeper, bk types.BankKeeper, _ keeper.Keeper) simtypes.Operation { - return func( - r *rand.Rand, app simtypes.AppEntrypoint, ctx sdk.Context, accs []simtypes.Account, chainID string, - ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { - funder, _ := simtypes.RandomAcc(r, accs) - - account := ak.GetAccount(ctx, funder.Address) - spendable := bk.SpendableCoins(ctx, account.GetAddress()) - - fundAmount := simtypes.RandSubsetCoins(r, spendable) - if fundAmount.Empty() { - return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(&types.MsgFundCommunityPool{}), "fund amount is empty"), nil, nil - } - - var ( - fees sdk.Coins - err error - ) - - coins, hasNeg := spendable.SafeSub(fundAmount...) - if !hasNeg { - fees, err = simtypes.RandomFees(r, coins) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(&types.MsgFundCommunityPool{}), "unable to generate fees"), nil, err - } - } - - funderAddr, err := ak.AddressCodec().BytesToString(funder.Address) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(&types.MsgFundCommunityPool{}), "unable to get funder address"), nil, err - } - msg := types.NewMsgFundCommunityPool(fundAmount, funderAddr) - - txCtx := simulation.OperationInput{ - R: r, - App: app, - TxGen: txConfig, - Cdc: nil, - Msg: msg, - Context: ctx, - SimAccount: funder, - AccountKeeper: ak, - ModuleName: types.ModuleName, - } - - return simulation.GenAndDeliverTx(txCtx, fees) - } -} diff --git a/x/protocolpool/simulation/proposals.go b/x/protocolpool/simulation/proposals.go deleted file mode 100644 index 0afddda38f01..000000000000 --- a/x/protocolpool/simulation/proposals.go +++ /dev/null @@ -1,57 +0,0 @@ -package simulation - -import ( - "context" - "math/rand" - - coreaddress "cosmossdk.io/core/address" - pooltypes "cosmossdk.io/x/protocolpool/types" - - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/types/address" - simtypes "github.com/cosmos/cosmos-sdk/types/simulation" - "github.com/cosmos/cosmos-sdk/x/simulation" -) - -const ( - OpWeightMsgCommunityPoolSpend = "op_weight_msg_community_pool_spend" - - DefaultWeightMsgCommunityPoolSpend int = 50 -) - -func ProposalMsgs() []simtypes.WeightedProposalMsg { - return []simtypes.WeightedProposalMsg{ - simulation.NewWeightedProposalMsgX( - OpWeightMsgCommunityPoolSpend, - DefaultWeightMsgCommunityPoolSpend, - SimulateMsgCommunityPoolSpend, - ), - } -} - -func SimulateMsgCommunityPoolSpend(_ context.Context, r *rand.Rand, _ []simtypes.Account, cdc coreaddress.Codec) (sdk.Msg, error) { - // use the default gov module account address as authority - var authority sdk.AccAddress = address.Module("gov") - - accs := simtypes.RandomAccounts(r, 5) - acc, _ := simtypes.RandomAcc(r, accs) - - coins, err := sdk.ParseCoinsNormalized("100stake,2testtoken") - if err != nil { - return nil, err - } - - authorityAddr, err := cdc.BytesToString(authority) - if err != nil { - return nil, err - } - recipentAddr, err := cdc.BytesToString(acc.Address) - if err != nil { - return nil, err - } - return &pooltypes.MsgCommunityPoolSpend{ - Authority: authorityAddr, - Recipient: recipentAddr, - Amount: coins, - }, nil -} diff --git a/x/protocolpool/simulation/proposals_test.go b/x/protocolpool/simulation/proposals_test.go deleted file mode 100644 index b452b01970fc..000000000000 --- a/x/protocolpool/simulation/proposals_test.go +++ /dev/null @@ -1,48 +0,0 @@ -package simulation_test - -import ( - "context" - "math/rand" - "testing" - - "gotest.tools/v3/assert" - - "cosmossdk.io/x/protocolpool/simulation" - pooltypes "cosmossdk.io/x/protocolpool/types" - - codectestutil "github.com/cosmos/cosmos-sdk/codec/testutil" - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/types/address" - simtypes "github.com/cosmos/cosmos-sdk/types/simulation" -) - -func TestProposalMsgs(t *testing.T) { - // initialize parameters - s := rand.NewSource(1) - r := rand.New(s) - addressCodec := codectestutil.CodecOptions{}.GetAddressCodec() - accounts := simtypes.RandomAccounts(r, 3) - - // execute ProposalMsgs function - weightedProposalMsgs := simulation.ProposalMsgs() - assert.Assert(t, len(weightedProposalMsgs) == 1) - - w0 := weightedProposalMsgs[0] - - // tests w0 interface: - assert.Equal(t, simulation.OpWeightMsgCommunityPoolSpend, w0.AppParamsKey()) - assert.Equal(t, simulation.DefaultWeightMsgCommunityPoolSpend, w0.DefaultWeight()) - - msg, err := w0.MsgSimulatorFn()(context.Background(), r, accounts, addressCodec) - assert.NilError(t, err) - msgCommunityPoolSpend, ok := msg.(*pooltypes.MsgCommunityPoolSpend) - assert.Assert(t, ok) - - coins, err := sdk.ParseCoinsNormalized("100stake,2testtoken") - assert.NilError(t, err) - - authAddr, err := addressCodec.BytesToString(address.Module("gov")) - assert.NilError(t, err) - assert.Equal(t, authAddr, msgCommunityPoolSpend.Authority) - assert.Assert(t, msgCommunityPoolSpend.Amount.Equal(coins)) -} diff --git a/x/simulation/client/cli/flags.go b/x/simulation/client/cli/flags.go index 311ce7017d85..1dc05fa47f29 100644 --- a/x/simulation/client/cli/flags.go +++ b/x/simulation/client/cli/flags.go @@ -30,6 +30,7 @@ var ( FlagPeriodValue uint FlagGenesisTimeValue int64 FlagSigverifyTxValue bool + FlagFauxMerkle bool ) // GetSimulatorFlags gets the values of all the available simulation flags @@ -54,6 +55,7 @@ func GetSimulatorFlags() { flag.UintVar(&FlagPeriodValue, "Period", 0, "run slow invariants only once every period assertions") flag.Int64Var(&FlagGenesisTimeValue, "GenesisTime", time.Now().Unix(), "use current time as genesis UNIX time for default") flag.BoolVar(&FlagSigverifyTxValue, "SigverifyTx", true, "whether to sigverify check for transaction ") + flag.BoolVar(&FlagFauxMerkle, "FauxMerkle", false, "use faux merkle instead of iavl") } // NewConfigFromFlags creates a simulation from the retrieved values of the flags. @@ -73,5 +75,6 @@ func NewConfigFromFlags() simulation.Config { Lean: FlagLeanValue, Commit: FlagCommitValue, DBBackend: FlagDBBackendValue, + FauxMerkle: FlagFauxMerkle, } } diff --git a/x/simulation/log.go b/x/simulation/log.go index c1f9c439e10b..4547e8f96d05 100644 --- a/x/simulation/log.go +++ b/x/simulation/log.go @@ -76,7 +76,7 @@ func createLogFile(seed int64) *os.File { if err != nil { panic(err) } - fmt.Printf("Logs to writing to %s\n", filePath) + fmt.Printf("Logs to writing to %q\n", filePath) return f } diff --git a/x/simulation/mock_cometbft.go b/x/simulation/mock_cometbft.go index 0dbfaec4654d..691494c64fe7 100644 --- a/x/simulation/mock_cometbft.go +++ b/x/simulation/mock_cometbft.go @@ -92,9 +92,9 @@ func updateValidators( if update.Power == 0 { if _, ok := current[str]; !ok { - tb.Fatalf("tried to delete a nonexistent validator: %s", str) + tb.Logf("tried to delete a nonexistent validator: %s", str) + continue } - event("end_block", "validator_updates", "kicked") delete(current, str) } else if _, ok := current[str]; ok { @@ -151,10 +151,13 @@ func RandomRequestFinalizeBlock( signed = false } + var commitStatus cmtproto.BlockIDFlag if signed { event("begin_block", "signing", "signed") + commitStatus = cmtproto.BlockIDFlagCommit } else { event("begin_block", "signing", "missed") + commitStatus = cmtproto.BlockIDFlagAbsent } voteInfos[i] = abci.VoteInfo{ @@ -162,7 +165,7 @@ func RandomRequestFinalizeBlock( Address: SumTruncated(mVal.val.PubKeyBytes), Power: mVal.val.Power, }, - BlockIdFlag: cmtproto.BlockIDFlagCommit, + BlockIdFlag: commitStatus, } } @@ -187,15 +190,17 @@ func RandomRequestFinalizeBlock( params.evidenceFraction = 0.9 } + totalBlocksProcessed := len(pastTimes) + startHeight := blockHeight - int64(totalBlocksProcessed) + 1 for r.Float64() < params.EvidenceFraction() { vals := voteInfos height := blockHeight misbehaviorTime := time - if r.Float64() < params.PastEvidenceFraction() && height > 1 { - height = int64(r.Intn(int(height)-1)) + 1 // CometBFT starts at height 1 - // array indices offset by one - misbehaviorTime = pastTimes[height-1] - vals = pastVoteInfos[height-1] + if r.Float64() < params.PastEvidenceFraction() && totalBlocksProcessed > 1 { + n := int64(r.Intn(totalBlocksProcessed)) + misbehaviorTime = pastTimes[n] + vals = pastVoteInfos[n] + height = startHeight + n } validator := vals[r.Intn(len(vals))].Validator diff --git a/x/simulation/operation.go b/x/simulation/operation.go index 8146ef15273a..6ba092713f94 100644 --- a/x/simulation/operation.go +++ b/x/simulation/operation.go @@ -76,13 +76,12 @@ func NewOperationQueue() OperationQueue { } // queueOperations adds all future operations into the operation queue. -func queueOperations(queuedOps OperationQueue, queuedTimeOps, futureOps []simulation.FutureOperation) { +func queueOperations(queuedOps OperationQueue, queuedTimeOps *[]simulation.FutureOperation, futureOps []simulation.FutureOperation) { if futureOps == nil { return } for _, futureOp := range futureOps { - futureOp := futureOp if futureOp.BlockHeight != 0 { if val, ok := queuedOps[futureOp.BlockHeight]; ok { queuedOps[futureOp.BlockHeight] = append(val, futureOp.Op) @@ -96,15 +95,15 @@ func queueOperations(queuedOps OperationQueue, queuedTimeOps, futureOps []simula // TODO: Replace with proper sorted data structure, so don't have the // copy entire slice index := sort.Search( - len(queuedTimeOps), + len(*queuedTimeOps), func(i int) bool { - return queuedTimeOps[i].BlockTime.After(futureOp.BlockTime) + return (*queuedTimeOps)[i].BlockTime.After(futureOp.BlockTime) }, ) - queuedTimeOps = append(queuedTimeOps, simulation.FutureOperation{}) - copy(queuedTimeOps[index+1:], queuedTimeOps[index:]) - queuedTimeOps[index] = futureOp + *queuedTimeOps = append(*queuedTimeOps, simulation.FutureOperation{}) + copy((*queuedTimeOps)[index+1:], (*queuedTimeOps)[index:]) + (*queuedTimeOps)[index] = futureOp } } diff --git a/x/simulation/params.go b/x/simulation/params.go index 4fce44cff82e..1c6032c867c1 100644 --- a/x/simulation/params.go +++ b/x/simulation/params.go @@ -185,8 +185,8 @@ func (w WeightedProposalContent) ContentSimulatorFn() simulation.ContentSimulato // Consensus Params -// randomConsensusParams returns random simulation consensus parameters, it extracts the Evidence from the Staking genesis state. -func randomConsensusParams(r *rand.Rand, appState json.RawMessage, cdc codec.JSONCodec, maxGas int64) *cmtproto.ConsensusParams { +// RandomConsensusParams returns random simulation consensus parameters, it extracts the Evidence from the Staking genesis state. +func RandomConsensusParams(r *rand.Rand, appState json.RawMessage, cdc codec.JSONCodec, maxGas int64) *cmtproto.ConsensusParams { var genesisState map[string]json.RawMessage err := json.Unmarshal(appState, &genesisState) if err != nil { diff --git a/x/simulation/params_test.go b/x/simulation/params_test.go index e4d6f380d101..1e05e3adadc8 100644 --- a/x/simulation/params_test.go +++ b/x/simulation/params_test.go @@ -1,6 +1,7 @@ package simulation import ( + "context" "fmt" "math/rand" "testing" @@ -29,7 +30,7 @@ func TestNewWeightedProposalContent(t *testing.T) { key := "theKey" weight := 1 content := &testContent{} - f := func(r *rand.Rand, ctx sdk.Context, accs []simtypes.Account) simtypes.Content { //nolint:staticcheck // used for legacy testing + f := func(r *rand.Rand, ctx context.Context, accs []simtypes.Account) simtypes.Content { //nolint:staticcheck // used for legacy testing return content } diff --git a/x/simulation/simulate.go b/x/simulation/simulate.go index cd4fbe590799..3cd8c5c4f66e 100644 --- a/x/simulation/simulate.go +++ b/x/simulation/simulate.go @@ -8,6 +8,7 @@ import ( "fmt" "io" "math/rand" + "slices" "testing" "time" @@ -21,7 +22,7 @@ import ( "github.com/cosmos/cosmos-sdk/baseapp" "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/types/simulation" + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" ) const AverageBlockTime = 6 * time.Second @@ -30,23 +31,24 @@ const AverageBlockTime = 6 * time.Second func initChain( r *rand.Rand, params Params, - accounts []simulation.Account, + accounts []simtypes.Account, app *baseapp.BaseApp, - appStateFn simulation.AppStateFn, - config simulation.Config, + appStateFn simtypes.AppStateFn, + config simtypes.Config, cdc codec.JSONCodec, -) (mockValidators, time.Time, []simulation.Account, string) { +) (mockValidators, time.Time, []simtypes.Account, string) { blockMaxGas := int64(-1) if config.BlockMaxGas > 0 { blockMaxGas = config.BlockMaxGas } appState, accounts, chainID, genesisTimestamp := appStateFn(r, accounts, config) - consensusParams := randomConsensusParams(r, appState, cdc, blockMaxGas) + consensusParams := RandomConsensusParams(r, appState, cdc, blockMaxGas) req := abci.InitChainRequest{ AppStateBytes: appState, ChainId: chainID, ConsensusParams: consensusParams, Time: genesisTimestamp, + InitialHeight: int64(config.InitialBlockHeight), } res, err := app.InitChain(&req) if err != nil { @@ -59,22 +61,22 @@ func initChain( // SimulateFromSeed tests an application by running the provided // operations, testing the provided invariants, but using the provided config.Seed. -func SimulateFromSeed( // exists for backwards compatibility only +func SimulateFromSeed( tb testing.TB, logger corelog.Logger, w io.Writer, app *baseapp.BaseApp, - appStateFn simulation.AppStateFn, - randAccFn simulation.RandomAccountFn, + appStateFn simtypes.AppStateFn, + randAccFn simtypes.RandomAccountFn, ops WeightedOperations, blockedAddrs map[string]bool, - config simulation.Config, + config simtypes.Config, cdc codec.JSONCodec, addressCodec address.Codec, -) (exportedParams Params, err error) { +) (exportedParams Params, accs []simtypes.Account, err error) { tb.Helper() mode, _, _ := getTestingMode(tb) - return SimulateFromSeedX(tb, logger, w, app, appStateFn, randAccFn, ops, blockedAddrs, config, cdc, addressCodec, NewLogWriter(mode)) + return SimulateFromSeedX(tb, logger, w, app, appStateFn, randAccFn, ops, blockedAddrs, config, cdc, NewLogWriter(mode)) } // SimulateFromSeedX tests an application by running the provided @@ -84,16 +86,20 @@ func SimulateFromSeedX( logger corelog.Logger, w io.Writer, app *baseapp.BaseApp, - appStateFn simulation.AppStateFn, - randAccFn simulation.RandomAccountFn, + appStateFn simtypes.AppStateFn, + randAccFn simtypes.RandomAccountFn, ops WeightedOperations, blockedAddrs map[string]bool, - config simulation.Config, + config simtypes.Config, cdc codec.JSONCodec, - addressCodec address.Codec, logWriter LogWriter, -) (exportedParams Params, err error) { +) (exportedParams Params, accs []simtypes.Account, err error) { tb.Helper() + defer func() { + if err != nil { + logWriter.PrintLogs() + } + }() // in case we have to end early, don't os.Exit so that we can run cleanup code. testingMode, _, b := getTestingMode(tb) @@ -105,7 +111,7 @@ func SimulateFromSeedX( logger.Debug("Randomized simulation setup", "params", mustMarshalJSONIndent(params)) timeDiff := maxTimePerBlock - minTimePerBlock - accs := randAccFn(r, params.NumKeys()) + accs = randAccFn(r, params.NumKeys()) eventStats := NewEventStats() // Second variable to keep pending validator set (delayed one block since @@ -114,31 +120,25 @@ func SimulateFromSeedX( // At least 2 accounts must be added here, otherwise when executing SimulateMsgSend // two accounts will be selected to meet the conditions from != to and it will fall into an infinite loop. if len(accs) <= 1 { - return params, errors.New("at least two genesis accounts are required") + return params, accs, errors.New("at least two genesis accounts are required") } config.ChainID = chainID // remove module account address if they exist in accs - var tmpAccs []simulation.Account - - for _, acc := range accs { - accAddr, err := addressCodec.BytesToString(acc.Address) - if err != nil { - return params, err - } - if !blockedAddrs[accAddr] { - tmpAccs = append(tmpAccs, acc) - } - } - - accs = tmpAccs + accs = slices.DeleteFunc(accs, func(acc simtypes.Account) bool { + return blockedAddrs[acc.AddressBech32] + }) nextValidators := validators + if len(nextValidators) == 0 { + tb.Skip("skipping: empty validator set in genesis") + return params, accs, nil + } var ( pastTimes []time.Time pastVoteInfos [][]abci.VoteInfo - timeOperationQueue []simulation.FutureOperation + timeOperationQueue []simtypes.FutureOperation blockHeight = int64(config.InitialBlockHeight) proposerAddress = validators.randomProposer(r) @@ -168,7 +168,7 @@ func SimulateFromSeedX( eventStats.Tally, ops, operationQueue, - timeOperationQueue, + &timeOperationQueue, logWriter, config, ) @@ -191,6 +191,10 @@ func SimulateFromSeedX( exportedParams = params } + if _, err := app.FinalizeBlock(finalizeBlockReq); err != nil { + return params, accs, fmt.Errorf("block finalization failed at height %d: %+w", blockHeight, err) + } + for blockHeight < int64(config.NumBlocks+config.InitialBlockHeight) { pastTimes = append(pastTimes, blockTime) pastVoteInfos = append(pastVoteInfos, finalizeBlockReq.DecidedLastCommit.Votes) @@ -200,7 +204,7 @@ func SimulateFromSeedX( res, err := app.FinalizeBlock(finalizeBlockReq) if err != nil { - return params, fmt.Errorf("block finalization failed at height %d: %w", blockHeight, err) + return params, accs, fmt.Errorf("block finalization failed at height %d: %w", blockHeight, err) } ctx := app.NewContextLegacy(false, cmtproto.Header{ @@ -219,15 +223,14 @@ func SimulateFromSeedX( tb, operationQueue, blockTime, int(blockHeight), r, app, ctx, accs, logWriter, eventStats.Tally, config.Lean, config.ChainID, ) - numQueuedTimeOpsRan, timeFutureOps := runQueuedTimeOperations(tb, - timeOperationQueue, int(blockHeight), blockTime, + &timeOperationQueue, int(blockHeight), blockTime, r, app, ctx, accs, logWriter, eventStats.Tally, config.Lean, config.ChainID, ) futureOps = append(futureOps, timeFutureOps...) - queueOperations(operationQueue, timeOperationQueue, futureOps) + queueOperations(operationQueue, &timeOperationQueue, futureOps) // run standard operations operations := blockSimulator(r, app, ctx, accs, cmtproto.Header{ @@ -237,7 +240,6 @@ func SimulateFromSeedX( ChainID: config.ChainID, }) opCount += operations + numQueuedOpsRan + numQueuedTimeOpsRan - blockHeight++ logWriter.AddEntry(EndBlockEntry(blockTime, blockHeight)) @@ -249,7 +251,7 @@ func SimulateFromSeedX( if config.Commit { app.SimWriteState() if _, err := app.Commit(); err != nil { - return params, fmt.Errorf("commit failed at height %d: %w", blockHeight, err) + return params, accs, fmt.Errorf("commit failed at height %d: %w", blockHeight, err) } } @@ -266,13 +268,16 @@ func SimulateFromSeedX( // on the next block validators = nextValidators nextValidators = updateValidators(tb, r, params, validators, res.ValidatorUpdates, eventStats.Tally) + if len(nextValidators) == 0 { + tb.Skip("skipping: empty validator set") + return exportedParams, accs, err + } // update the exported params if config.ExportParamsPath != "" && int64(config.ExportParamsHeight) == blockHeight { exportedParams = params } } - logger.Info("Simulation complete", "height", blockHeight, "block-time", blockTime, "opsCount", opCount, "run-time", time.Since(startTime), "app-hash", hex.EncodeToString(app.LastCommitID().Hash)) @@ -282,14 +287,14 @@ func SimulateFromSeedX( } else { eventStats.Print(w) } - return exportedParams, err + return exportedParams, accs, err } type blockSimFn func( r *rand.Rand, - app *baseapp.BaseApp, + app simtypes.AppEntrypoint, ctx sdk.Context, - accounts []simulation.Account, + accounts []simtypes.Account, header cmtproto.Header, ) (opCount int) @@ -297,8 +302,8 @@ type blockSimFn func( // parameters being passed every time, to minimize memory overhead. func createBlockSimulator(tb testing.TB, printProgress bool, w io.Writer, params Params, event func(route, op, evResult string), ops WeightedOperations, - operationQueue OperationQueue, timeOperationQueue []simulation.FutureOperation, - logWriter LogWriter, config simulation.Config, + operationQueue OperationQueue, timeOperationQueue *[]simtypes.FutureOperation, + logWriter LogWriter, config simtypes.Config, ) blockSimFn { tb.Helper() lastBlockSizeState := 0 // state for [4 * uniform distribution] @@ -306,7 +311,7 @@ func createBlockSimulator(tb testing.TB, printProgress bool, w io.Writer, params selectOp := ops.getSelectOpFn() return func( - r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, accounts []simulation.Account, header cmtproto.Header, + r *rand.Rand, app simtypes.AppEntrypoint, ctx sdk.Context, accounts []simtypes.Account, header cmtproto.Header, ) (opCount int) { _, _ = fmt.Fprintf( w, "\rSimulating... block %d/%d, operation %d/%d.", @@ -315,7 +320,7 @@ func createBlockSimulator(tb testing.TB, printProgress bool, w io.Writer, params lastBlockSizeState, blocksize = getBlockSize(r, params, lastBlockSizeState, config.BlockSize) type opAndR struct { - op simulation.Operation + op simtypes.Operation rand *rand.Rand } @@ -363,11 +368,11 @@ Comment: %s`, } } -func runQueuedOperations(tb testing.TB, queueOps map[int][]simulation.Operation, +func runQueuedOperations(tb testing.TB, queueOps map[int][]simtypes.Operation, blockTime time.Time, height int, r *rand.Rand, app *baseapp.BaseApp, - ctx sdk.Context, accounts []simulation.Account, logWriter LogWriter, + ctx sdk.Context, accounts []simtypes.Account, logWriter LogWriter, event func(route, op, evResult string), lean bool, chainID string, -) (numOpsRan int, allFutureOps []simulation.FutureOperation) { +) (numOpsRan int, allFutureOps []simtypes.FutureOperation) { tb.Helper() queuedOp, ok := queueOps[height] if !ok { @@ -375,11 +380,15 @@ func runQueuedOperations(tb testing.TB, queueOps map[int][]simulation.Operation, } // Keep all future operations - allFutureOps = make([]simulation.FutureOperation, 0) + allFutureOps = make([]simtypes.FutureOperation, 0) numOpsRan = len(queuedOp) for i := 0; i < numOpsRan; i++ { opMsg, futureOps, err := queuedOp[i](r, app, ctx, accounts, chainID) + if err != nil { + logWriter.PrintLogs() + tb.FailNow() + } if len(futureOps) > 0 { allFutureOps = append(allFutureOps, futureOps...) } @@ -387,49 +396,44 @@ func runQueuedOperations(tb testing.TB, queueOps map[int][]simulation.Operation, opMsg.LogEvent(event) if !lean || opMsg.OK { - logWriter.AddEntry((QueuedMsgEntry(blockTime, int64(height), opMsg))) + logWriter.AddEntry(QueuedMsgEntry(blockTime, int64(height), opMsg)) } - if err != nil { - logWriter.PrintLogs() - tb.FailNow() - } } delete(queueOps, height) return numOpsRan, allFutureOps } -func runQueuedTimeOperations(tb testing.TB, queueOps []simulation.FutureOperation, +func runQueuedTimeOperations(tb testing.TB, queueOps *[]simtypes.FutureOperation, height int, currentTime time.Time, r *rand.Rand, - app *baseapp.BaseApp, ctx sdk.Context, accounts []simulation.Account, + app *baseapp.BaseApp, ctx sdk.Context, accounts []simtypes.Account, logWriter LogWriter, event func(route, op, evResult string), lean bool, chainID string, -) (numOpsRan int, allFutureOps []simulation.FutureOperation) { +) (numOpsRan int, allFutureOps []simtypes.FutureOperation) { tb.Helper() // Keep all future operations - allFutureOps = make([]simulation.FutureOperation, 0) - numOpsRan = 0 - for len(queueOps) > 0 && currentTime.After(queueOps[0].BlockTime) { - opMsg, futureOps, err := queueOps[0].Op(r, app, ctx, accounts, chainID) + for len(*queueOps) > 0 && currentTime.After((*queueOps)[0].BlockTime) { + if qOp := (*queueOps)[0]; qOp.Op != nil { + opMsg, futureOps, err := qOp.Op(r, app, ctx, accounts, chainID) - opMsg.LogEvent(event) + opMsg.LogEvent(event) - if !lean || opMsg.OK { - logWriter.AddEntry(QueuedMsgEntry(currentTime, int64(height), opMsg)) - } + if !lean || opMsg.OK { + logWriter.AddEntry(QueuedMsgEntry(currentTime, int64(height), opMsg)) + } - if err != nil { - logWriter.PrintLogs() - tb.FailNow() - } + if err != nil { + logWriter.PrintLogs() + tb.Fatal(err) + } - if len(futureOps) > 0 { - allFutureOps = append(allFutureOps, futureOps...) + if len(futureOps) > 0 { + allFutureOps = append(allFutureOps, futureOps...) + } } - - queueOps = queueOps[1:] + *queueOps = slices.Delete(*queueOps, 0, 1) numOpsRan++ } diff --git a/x/simulation/simulate_test.go b/x/simulation/simulate_test.go new file mode 100644 index 000000000000..31fe943acfa0 --- /dev/null +++ b/x/simulation/simulate_test.go @@ -0,0 +1,57 @@ +package simulation + +import ( + "math/rand" + "testing" + "time" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + sdk "github.com/cosmos/cosmos-sdk/types" + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" +) + +func TestRunQueuedTimeOperations(t *testing.T) { + r := rand.New(rand.NewSource(time.Now().UnixNano())) + ctx := sdk.Context{} + lw := NewLogWriter(true) + noopEvent := func(route, op, evResult string) {} + var acc []simtypes.Account + noOp := simtypes.FutureOperation{ + Op: func(gotR *rand.Rand, gotApp simtypes.AppEntrypoint, ctx sdk.Context, accounts []simtypes.Account, chainID string) (OperationMsg simtypes.OperationMsg, futureOps []simtypes.FutureOperation, err error) { + return simtypes.OperationMsg{}, nil, nil + }, + } + futureOp := simtypes.FutureOperation{ + Op: func(gotR *rand.Rand, gotApp simtypes.AppEntrypoint, ctx sdk.Context, accounts []simtypes.Account, chainID string) (OperationMsg simtypes.OperationMsg, futureOps []simtypes.FutureOperation, err error) { + return simtypes.OperationMsg{}, []simtypes.FutureOperation{noOp}, nil + }, + } + + specs := map[string]struct { + queueOps []simtypes.FutureOperation + expOps []simtypes.FutureOperation + }{ + "empty": {}, + "single": { + queueOps: []simtypes.FutureOperation{noOp}, + }, + "multi": { + queueOps: []simtypes.FutureOperation{noOp, noOp}, + }, + "future op": { + queueOps: []simtypes.FutureOperation{futureOp}, + expOps: []simtypes.FutureOperation{noOp}, + }, + } + for name, spec := range specs { + t.Run(name, func(t *testing.T) { + expOps := len(spec.queueOps) + n, fOps := runQueuedTimeOperations(t, &spec.queueOps, 0, time.Now(), r, nil, ctx, acc, lw, noopEvent, false, "testing") + require.Equal(t, expOps, n) + assert.Empty(t, spec.queueOps) + assert.Len(t, fOps, len(spec.expOps)) // using len as equal fails with Go 1.23 now + }) + } +} diff --git a/x/slashing/README.md b/x/slashing/README.md index c6da11e0ce2d..942b3afcc052 100644 --- a/x/slashing/README.md +++ b/x/slashing/README.md @@ -143,7 +143,7 @@ bonded validator. The `SignedBlocksWindow` parameter defines the size The information stored for tracking validator liveness is as follows: ```protobuf reference -https://github.com/cosmos/cosmos-sdk/blob/release/v0.52.x/x/slashing/proto/cosmos/slashing/v1beta1/slashing.proto#L13-L35 +https://github.com/cosmos/cosmos-sdk/blob/v0.52.0-beta.1/x/slashing/proto/cosmos/slashing/v1beta1/slashing.proto#L13-L35 ``` ### Params @@ -154,7 +154,7 @@ it can be updated with governance or the address with authority. * Params: `0x00 | ProtocolBuffer(Params)` ```protobuf reference -https://github.com/cosmos/cosmos-sdk/blob/release/v0.52.x/x/slashing/proto/cosmos/slashing/v1beta1/slashing.proto#L37-L62 +https://github.com/cosmos/cosmos-sdk/blob/v0.52.0-beta.1/x/slashing/proto/cosmos/slashing/v1beta1/slashing.proto#L37-L62 ``` ## Messages @@ -312,6 +312,7 @@ The following hooks impact the slashing state: * `AfterValidatorBonded` creates a `ValidatorSigningInfo` instance as described in the following section. * `AfterValidatorCreated` stores a validator's consensus key. * `AfterValidatorRemoved` removes a validator's consensus key. +* `AfterConsensusPubKeyUpdate` handles the rotation of signing info and updates the address-pubkey relation after a consensus key update. ### Validator Bonded @@ -633,6 +634,20 @@ Example: simd tx slashing unjail --from mykey ``` +#### update-params-proposal + +The `update-params-proposal` command allows users to submit a governance proposal to update the slashing module parameters: + +```bash +simd tx slashing update-params-proposal [flags] +``` + +Example: + +```bash +simd tx slashing update-params-proposal '{ "signed_blocks_window": "100" }' +``` + ### gRPC A user can query the `slashing` module using gRPC endpoints. diff --git a/x/slashing/abci.go b/x/slashing/abci.go index e99b6acea574..00318f1f5637 100644 --- a/x/slashing/abci.go +++ b/x/slashing/abci.go @@ -13,7 +13,8 @@ import ( // BeginBlocker check for infraction evidence or downtime of validators // on every begin block func BeginBlocker(ctx context.Context, k keeper.Keeper, cometService comet.Service) error { - defer telemetry.ModuleMeasureSince(types.ModuleName, telemetry.Now(), telemetry.MetricKeyBeginBlocker) + start := telemetry.Now() + defer telemetry.ModuleMeasureSince(types.ModuleName, start, telemetry.MetricKeyBeginBlocker) // Retrieve CometBFT info, then iterate through all validator votes // from the last commit. For each vote, handle the validator's signature, potentially diff --git a/x/slashing/go.mod b/x/slashing/go.mod index 9c0050d83d28..c207b1c5317b 100644 --- a/x/slashing/go.mod +++ b/x/slashing/go.mod @@ -3,10 +3,10 @@ module cosmossdk.io/x/slashing go 1.23.1 require ( - cosmossdk.io/api v0.7.5 + cosmossdk.io/api v0.7.6 cosmossdk.io/collections v0.4.0 - cosmossdk.io/core v1.0.0-alpha.2 - cosmossdk.io/core/testing v0.0.0-00010101000000-000000000000 + cosmossdk.io/core v1.0.0-alpha.4 + cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29 cosmossdk.io/depinject v1.0.0 cosmossdk.io/errors v1.0.1 cosmossdk.io/math v1.3.0 @@ -20,8 +20,8 @@ require ( github.com/golang/protobuf v1.5.4 github.com/grpc-ecosystem/grpc-gateway v1.16.0 github.com/stretchr/testify v1.9.0 - google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 - google.golang.org/grpc v1.66.2 + google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 + google.golang.org/grpc v1.67.1 google.golang.org/protobuf v1.34.2 gotest.tools/v3 v3.5.1 ) @@ -30,7 +30,7 @@ require ( buf.build/gen/go/cometbft/cometbft/protocolbuffers/go v1.34.2-20240701160653-fedbb9acfd2f.2 // indirect buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.34.2-20240130113600-88ef6483f90f.2 // indirect cosmossdk.io/log v1.4.1 // indirect - cosmossdk.io/schema v0.2.0 // indirect + cosmossdk.io/schema v0.3.1-0.20240930054013-7c6e0388a3f9 // indirect cosmossdk.io/x/bank v0.0.0-20240226161501-23359a0b6d91 // indirect cosmossdk.io/x/tx v0.13.3 // indirect filippo.io/edwards25519 v1.1.0 // indirect @@ -99,7 +99,7 @@ require ( github.com/hashicorp/hcl v1.0.0 // indirect github.com/hashicorp/yamux v0.1.1 // indirect github.com/hdevalence/ed25519consensus v0.2.0 // indirect - github.com/huandu/skiplist v1.2.0 // indirect + github.com/huandu/skiplist v1.2.1 // indirect github.com/iancoleman/strcase v0.3.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jmhodges/levigo v1.0.0 // indirect @@ -122,9 +122,9 @@ require ( github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/client_golang v1.20.3 // indirect + github.com/prometheus/client_golang v1.20.4 // indirect github.com/prometheus/client_model v0.6.1 // indirect - github.com/prometheus/common v0.59.1 // indirect + github.com/prometheus/common v0.60.0 // indirect github.com/prometheus/procfs v0.15.1 // indirect github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect github.com/rogpeppe/go-internal v1.12.0 // indirect @@ -161,7 +161,7 @@ require ( golang.org/x/text v0.18.0 // indirect golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect pgregory.net/rapid v1.1.0 // indirect @@ -173,7 +173,6 @@ replace github.com/cosmos/cosmos-sdk => ../../. // TODO remove post spinning out all modules replace ( cosmossdk.io/api => ../../api - cosmossdk.io/core/testing => ../../core/testing cosmossdk.io/store => ../../store cosmossdk.io/x/bank => ../bank cosmossdk.io/x/staking => ../staking diff --git a/x/slashing/go.sum b/x/slashing/go.sum index 03e82f35386e..9600563cd537 100644 --- a/x/slashing/go.sum +++ b/x/slashing/go.sum @@ -6,8 +6,10 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cosmossdk.io/collections v0.4.0 h1:PFmwj2W8szgpD5nOd8GWH6AbYNi1f2J6akWXJ7P5t9s= cosmossdk.io/collections v0.4.0/go.mod h1:oa5lUING2dP+gdDquow+QjlF45eL1t4TJDypgGd+tv0= -cosmossdk.io/core v1.0.0-alpha.2 h1:epU0Xwces4Rgl5bMhHHkXGaGDcyucNGlC/JDH+Suckg= -cosmossdk.io/core v1.0.0-alpha.2/go.mod h1:abgLjeFLhtuKIYZWSPlVUgQBrKObO7ULV35KYfexE90= +cosmossdk.io/core v1.0.0-alpha.4 h1:9iuroT9ejDYETCsGkzkvs/wAY/5UFl7nCIINFRxyMJY= +cosmossdk.io/core v1.0.0-alpha.4/go.mod h1:3u9cWq1FAVtiiCrDPpo4LhR+9V6k/ycSG4/Y/tREWCY= +cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29 h1:NxxUo0GMJUbIuVg0R70e3cbn9eFTEuMr7ev1AFvypdY= +cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29/go.mod h1:8s2tPeJtSiQuoyPmr2Ag7meikonISO4Fv4MoO8+ORrs= cosmossdk.io/depinject v1.0.0 h1:dQaTu6+O6askNXO06+jyeUAnF2/ssKwrrszP9t5q050= cosmossdk.io/depinject v1.0.0/go.mod h1:zxK/h3HgHoA/eJVtiSsoaRaRA2D5U4cJ5thIG4ssbB8= cosmossdk.io/errors v1.0.1 h1:bzu+Kcr0kS/1DuPBtUFdWjzLqyUuCiyHjyJB6srBV/0= @@ -16,8 +18,8 @@ cosmossdk.io/log v1.4.1 h1:wKdjfDRbDyZRuWa8M+9nuvpVYxrEOwbD/CA8hvhU8QM= cosmossdk.io/log v1.4.1/go.mod h1:k08v0Pyq+gCP6phvdI6RCGhLf/r425UT6Rk/m+o74rU= cosmossdk.io/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE= cosmossdk.io/math v1.3.0/go.mod h1:vnRTxewy+M7BtXBNFybkuhSH4WfedVAAnERHgVFhp3k= -cosmossdk.io/schema v0.2.0 h1:UH5CR1DqUq8yP+5Np8PbvG4YX0zAUsTN2Qk6yThmfMk= -cosmossdk.io/schema v0.2.0/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= +cosmossdk.io/schema v0.3.1-0.20240930054013-7c6e0388a3f9 h1:DmOoS/1PeY6Ih0hAVlJ69kLMUrLV+TCbfICrZtB1vdU= +cosmossdk.io/schema v0.3.1-0.20240930054013-7c6e0388a3f9/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMbk2FiG/kXiLl8BRyzTWDw7gX/Hz7Dd5eDMs= @@ -294,8 +296,8 @@ github.com/hdevalence/ed25519consensus v0.2.0/go.mod h1:w3BHWjwJbFU29IRHL1Iqkw3s github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/huandu/go-assert v1.1.5 h1:fjemmA7sSfYHJD7CUqs9qTwwfdNAx7/j2/ZlHXzNB3c= github.com/huandu/go-assert v1.1.5/go.mod h1:yOLvuqZwmcHIC5rIzrBhT7D3Q9c3GFnd0JrPVhn/06U= -github.com/huandu/skiplist v1.2.0 h1:gox56QD77HzSC0w+Ws3MH3iie755GBJU1OER3h5VsYw= -github.com/huandu/skiplist v1.2.0/go.mod h1:7v3iFjLcSAzO4fN5B8dvebvo/qsfumiLiDXMrPiHF9w= +github.com/huandu/skiplist v1.2.1 h1:dTi93MgjwErA/8idWTzIw4Y1kZsMWx35fmI2c8Rij7w= +github.com/huandu/skiplist v1.2.1/go.mod h1:7v3iFjLcSAzO4fN5B8dvebvo/qsfumiLiDXMrPiHF9w= github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI= github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= @@ -404,8 +406,8 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= -github.com/prometheus/client_golang v1.20.3 h1:oPksm4K8B+Vt35tUhw6GbSNSgVlVSBH0qELP/7u83l4= -github.com/prometheus/client_golang v1.20.3/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_golang v1.20.4 h1:Tgh3Yr67PaOv/uTqloMsCEdeuFTatm5zIq5+qNN23vI= +github.com/prometheus/client_golang v1.20.4/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -414,8 +416,8 @@ github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= -github.com/prometheus/common v0.59.1 h1:LXb1quJHWm1P6wq/U824uxYi4Sg0oGvNeUm1z5dJoX0= -github.com/prometheus/common v0.59.1/go.mod h1:GpWM7dewqmVYcd7SmRaiWVe9SSqjf0UrwnYnpEZNuT0= +github.com/prometheus/common v0.60.0 h1:+V9PAREWNvJMAuJ1x1BaWl9dewMW4YrHZQbx0sJNllA= +github.com/prometheus/common v0.60.0/go.mod h1:h0LYf1R1deLSKtD4Vdg8gy4RuOvENW2J/h19V5NADQw= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/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= @@ -638,10 +640,10 @@ google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEY google.golang.org/genproto v0.0.0-20220314164441-57ef72a4c106/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E= google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de h1:F6qOa9AZTYJXOUEr4jDysRDLrm4PHePlge4v4TGAlxY= google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:VUhTRKeHn9wwcdrk73nvdC9gF178Tzhmt/qyaFcPLSo= -google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 h1:+rdxYoE3E5htTEWIe15GlN6IfvbURM//Jt0mmkmm6ZU= -google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117/go.mod h1:OimBR/bc1wPO9iV4NC2bpyjy3VnAwZh5EBPQdtaE5oo= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:pPJltXNxVzT4pK9yD8vR9X75DaWYYmLGMsEvBfFQZzQ= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= +google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 h1:wKguEg1hsxI2/L3hUYrpo1RVi48K+uTyzKqprwLXsb8= +google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142/go.mod h1:d6be+8HhtEtucleCbxpPW9PA9XwISACu8nvpPqF0BVo= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f h1:cUMEy+8oS78BWIH9OWazBkzbr090Od9tWBNtZHkOhf0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= @@ -652,8 +654,8 @@ google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= -google.golang.org/grpc v1.66.2 h1:3QdXkuq3Bkh7w+ywLdLvM56cmGvQHUMZpiCzt6Rqaoo= -google.golang.org/grpc v1.66.2/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y= +google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E= +google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= 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= diff --git a/x/slashing/keeper/msg_server_test.go b/x/slashing/keeper/msg_server_test.go index 39b04636328d..2554ac5fe2ab 100644 --- a/x/slashing/keeper/msg_server_test.go +++ b/x/slashing/keeper/msg_server_test.go @@ -135,7 +135,6 @@ func (s *KeeperTestSuite) TestUpdateParams() { } for _, tc := range testCases { - tc := tc s.Run(tc.name, func() { _, err := s.msgServer.UpdateParams(s.ctx, tc.request) if tc.expectErr { @@ -345,7 +344,6 @@ func (s *KeeperTestSuite) TestUnjail() { } for _, tc := range testCases { - tc := tc s.Run(tc.name, func() { req := tc.malleate() _, err := s.msgServer.Unjail(s.ctx, req) diff --git a/x/slashing/module.go b/x/slashing/module.go index e210daf33af8..8fbd57939533 100644 --- a/x/slashing/module.go +++ b/x/slashing/module.go @@ -18,6 +18,7 @@ import ( "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/codec" cdctypes "github.com/cosmos/cosmos-sdk/codec/types" + "github.com/cosmos/cosmos-sdk/simsx" "github.com/cosmos/cosmos-sdk/types/module" simtypes "github.com/cosmos/cosmos-sdk/types/simulation" ) @@ -40,12 +41,9 @@ var ( // AppModule implements an application module for the slashing module. type AppModule struct { cdc codec.Codec - registry cdctypes.InterfaceRegistry cometService comet.Service keeper keeper.Keeper - accountKeeper types.AccountKeeper - bankKeeper types.BankKeeper stakingKeeper types.StakingKeeper } @@ -61,10 +59,7 @@ func NewAppModule( ) AppModule { return AppModule{ cdc: cdc, - registry: registry, keeper: keeper, - accountKeeper: ak, - bankKeeper: bk, stakingKeeper: sk, cometService: cs, } @@ -171,9 +166,9 @@ func (AppModule) GenerateGenesisState(simState *module.SimulationState) { simulation.RandomizedGenState(simState) } -// ProposalMsgs returns msgs used for governance proposals for simulations. -func (AppModule) ProposalMsgs(simState module.SimulationState) []simtypes.WeightedProposalMsg { - return simulation.ProposalMsgs() +// ProposalMsgsX returns msgs used for governance proposals for simulations. +func (AppModule) ProposalMsgsX(weights simsx.WeightSource, reg simsx.Registry) { + reg.Add(weights.Get("msg_update_params", 100), simulation.MsgUpdateParamsFactory()) } // RegisterStoreDecoder registers a decoder for slashing module's types @@ -181,10 +176,8 @@ func (am AppModule) RegisterStoreDecoder(sdr simtypes.StoreDecoderRegistry) { sdr[types.StoreKey] = simulation.NewDecodeStore(am.cdc) } -// WeightedOperations returns the all the slashing module operations with their respective weights. -func (am AppModule) WeightedOperations(simState module.SimulationState) []simtypes.WeightedOperation { - return simulation.WeightedOperations( - am.registry, simState.AppParams, simState.Cdc, simState.TxConfig, - am.accountKeeper, am.bankKeeper, am.keeper, am.stakingKeeper, - ) +// WeightedOperationsX returns the all the slashing module operations with their respective weights. +func (am AppModule) WeightedOperationsX(weights simsx.WeightSource, reg simsx.Registry) { + // note: using old keys for backwards compatibility + reg.Add(weights.Get("msg_unjail", 20), simulation.MsgUnjailFactory(am.keeper, am.stakingKeeper)) } diff --git a/x/slashing/simulation/decoder_test.go b/x/slashing/simulation/decoder_test.go index 50d9887a491d..6a668a8ddfe7 100644 --- a/x/slashing/simulation/decoder_test.go +++ b/x/slashing/simulation/decoder_test.go @@ -50,7 +50,6 @@ func TestDecodeStore(t *testing.T) { {"other", "", true}, } for i, tt := range tests { - i, tt := i, tt t.Run(tt.name, func(t *testing.T) { if tt.panics { require.Panics(t, func() { dec(kvPairs.Pairs[i], kvPairs.Pairs[i]) }, tt.name) diff --git a/x/slashing/simulation/genesis.go b/x/slashing/simulation/genesis.go index 26ea1aeb4072..8316b06a7c20 100644 --- a/x/slashing/simulation/genesis.go +++ b/x/slashing/simulation/genesis.go @@ -1,8 +1,6 @@ package simulation import ( - "encoding/json" - "fmt" "math/rand" "time" @@ -71,10 +69,5 @@ func RandomizedGenState(simState *module.SimulationState) { slashingGenesis := types.NewGenesisState(params, []types.SigningInfo{}, []types.ValidatorMissedBlocks{}) - bz, err := json.MarshalIndent(&slashingGenesis, "", " ") - if err != nil { - panic(err) - } - fmt.Printf("Selected randomly generated slashing parameters:\n%s\n", bz) simState.GenState[types.ModuleName] = simState.Cdc.MustMarshalJSON(slashingGenesis) } diff --git a/x/slashing/simulation/msg_factory.go b/x/slashing/simulation/msg_factory.go new file mode 100644 index 000000000000..86a59544425c --- /dev/null +++ b/x/slashing/simulation/msg_factory.go @@ -0,0 +1,98 @@ +package simulation + +import ( + "context" + "errors" + "time" + + sdkmath "cosmossdk.io/math" + "cosmossdk.io/x/slashing/keeper" + "cosmossdk.io/x/slashing/types" + + "github.com/cosmos/cosmos-sdk/simsx" +) + +func MsgUnjailFactory(k keeper.Keeper, sk types.StakingKeeper) simsx.SimMsgFactoryX { + return simsx.NewSimMsgFactoryWithDeliveryResultHandler[*types.MsgUnjail](func(ctx context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter) ([]simsx.SimAccount, *types.MsgUnjail, simsx.SimDeliveryResultHandler) { + allVals, err := sk.GetAllValidators(ctx) + if err != nil { + reporter.Skip(err.Error()) + return nil, nil, nil + } + validator := simsx.OneOf(testData.Rand(), allVals) + if !validator.IsJailed() { + reporter.Skip("validator not jailed") + return nil, nil, nil + } + if validator.InvalidExRate() { + reporter.Skip("validator with invalid exchange rate") + return nil, nil, nil + } + + info, err := k.ValidatorSigningInfo.Get(ctx, must(validator.GetConsAddr())) + if err != nil { + reporter.Skip(err.Error()) + return nil, nil, nil + } + valOperBz := must(sk.ValidatorAddressCodec().StringToBytes(validator.GetOperator())) + valOper := testData.GetAccountbyAccAddr(reporter, valOperBz) + if reporter.IsSkipped() { + return nil, nil, nil + } + + selfDel, err := sk.Delegation(ctx, valOper.Address, valOperBz) + if selfDel == nil || err != nil { + reporter.Skip("no self delegation") + return nil, nil, nil + } + var handler simsx.SimDeliveryResultHandler + // result should fail if: + // - validator cannot be unjailed due to tombstone + // - validator is still in jailed period + // - self delegation too low + if info.Tombstoned || + simsx.BlockTime(ctx).Before(info.JailedUntil) || + selfDel.GetShares().IsNil() || + validator.TokensFromShares(selfDel.GetShares()).TruncateInt().LT(validator.GetMinSelfDelegation()) { + handler = func(err error) error { + if err == nil { + switch { + case info.Tombstoned: + return errors.New("validator should not have been unjailed if validator tombstoned") + case simsx.BlockTime(ctx).Before(info.JailedUntil): + return errors.New("validator unjailed while validator still in jail period") + case selfDel.GetShares().IsNil() || validator.TokensFromShares(selfDel.GetShares()).TruncateInt().LT(validator.GetMinSelfDelegation()): + return errors.New("validator unjailed even though self-delegation too low") + } + } + return nil + } + } + return []simsx.SimAccount{valOper}, types.NewMsgUnjail(validator.GetOperator()), handler + }) +} + +// MsgUpdateParamsFactory creates a gov proposal for param updates +func MsgUpdateParamsFactory() simsx.SimMsgFactoryFn[*types.MsgUpdateParams] { + return func(_ context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter) ([]simsx.SimAccount, *types.MsgUpdateParams) { + r := testData.Rand() + params := types.DefaultParams() + params.DowntimeJailDuration = time.Duration(r.Timestamp().UnixNano()) + params.SignedBlocksWindow = int64(r.IntInRange(1, 1000)) + params.MinSignedPerWindow = sdkmath.LegacyNewDecWithPrec(int64(r.IntInRange(1, 100)), 2) + params.SlashFractionDoubleSign = sdkmath.LegacyNewDecWithPrec(int64(r.IntInRange(1, 100)), 2) + params.SlashFractionDowntime = sdkmath.LegacyNewDecWithPrec(int64(r.IntInRange(1, 100)), 2) + + return nil, &types.MsgUpdateParams{ + Authority: testData.ModuleAccountAddress(reporter, "gov"), + Params: params, + } + } +} + +func must[T any](r T, err error) T { + if err != nil { + panic(err) + } + return r +} diff --git a/x/slashing/simulation/operations.go b/x/slashing/simulation/operations.go deleted file mode 100644 index e14cef141346..000000000000 --- a/x/slashing/simulation/operations.go +++ /dev/null @@ -1,159 +0,0 @@ -package simulation - -import ( - "errors" - "math/rand" - - "cosmossdk.io/x/slashing/keeper" - "cosmossdk.io/x/slashing/types" - - "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/codec" - codectypes "github.com/cosmos/cosmos-sdk/codec/types" - "github.com/cosmos/cosmos-sdk/testutil" - simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" - sdk "github.com/cosmos/cosmos-sdk/types" - simtypes "github.com/cosmos/cosmos-sdk/types/simulation" - "github.com/cosmos/cosmos-sdk/x/simulation" -) - -// Simulation operation weights constants -const ( - OpWeightMsgUnjail = "op_weight_msg_unjail" - - DefaultWeightMsgUnjail = 100 -) - -// WeightedOperations returns all the operations from the module with their respective weights -func WeightedOperations( - registry codectypes.InterfaceRegistry, - appParams simtypes.AppParams, - cdc codec.JSONCodec, - txGen client.TxConfig, - ak types.AccountKeeper, - bk types.BankKeeper, - k keeper.Keeper, - sk types.StakingKeeper, -) simulation.WeightedOperations { - var weightMsgUnjail int - appParams.GetOrGenerate(OpWeightMsgUnjail, &weightMsgUnjail, nil, func(_ *rand.Rand) { - weightMsgUnjail = DefaultWeightMsgUnjail - }) - - return simulation.WeightedOperations{ - simulation.NewWeightedOperation( - weightMsgUnjail, - SimulateMsgUnjail(codec.NewProtoCodec(registry), txGen, ak, bk, k, sk), - ), - } -} - -// SimulateMsgUnjail generates a MsgUnjail with random values -func SimulateMsgUnjail( - cdc *codec.ProtoCodec, - txGen client.TxConfig, - ak types.AccountKeeper, - bk types.BankKeeper, - k keeper.Keeper, - sk types.StakingKeeper, -) simtypes.Operation { - return func( - r *rand.Rand, app simtypes.AppEntrypoint, ctx sdk.Context, - accs []simtypes.Account, chainID string, - ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { - msgType := sdk.MsgTypeURL(&types.MsgUnjail{}) - - allVals, err := sk.GetAllValidators(ctx) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "unable to get all validators"), nil, err - } - - validator, ok := testutil.RandSliceElem(r, allVals) - if !ok { - return simtypes.NoOpMsg(types.ModuleName, msgType, "validator is not ok"), nil, nil // skip - } - - bz, err := sk.ValidatorAddressCodec().StringToBytes(validator.GetOperator()) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "unable to convert validator address to bytes"), nil, err - } - - simAccount, found := simtypes.FindAccount(accs, sdk.AccAddress(bz)) - if !found { - return simtypes.NoOpMsg(types.ModuleName, msgType, "unable to find account"), nil, nil // skip - } - - if !validator.IsJailed() { - // TODO: due to this condition this message is almost, if not always, skipped ! - return simtypes.NoOpMsg(types.ModuleName, msgType, "validator is not jailed"), nil, nil - } - - consAddr, err := validator.GetConsAddr() - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "unable to get validator consensus key"), nil, err - } - info, _ := k.ValidatorSigningInfo.Get(ctx, consAddr) - - selfDel, _ := sk.Delegation(ctx, simAccount.Address, bz) - if selfDel == nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "self delegation is nil"), nil, nil // skip - } - - account := ak.GetAccount(ctx, sdk.AccAddress(bz)) - spendable := bk.SpendableCoins(ctx, account.GetAddress()) - - fees, err := simtypes.RandomFees(r, spendable) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "unable to generate fees"), nil, nil - } - - msg := types.NewMsgUnjail(validator.GetOperator()) - - tx, err := simtestutil.GenSignedMockTx( - r, - txGen, - []sdk.Msg{msg}, - fees, - simtestutil.DefaultGenTxGas, - chainID, - []uint64{account.GetAccountNumber()}, - []uint64{account.GetSequence()}, - simAccount.PrivKey, - ) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(msg), "unable to generate mock tx"), nil, err - } - - _, res, err := app.SimDeliver(txGen.TxEncoder(), tx) - - // result should fail if: - // - validator cannot be unjailed due to tombstone - // - validator is still in jailed period - // - self delegation too low - if info.Tombstoned || - ctx.HeaderInfo().Time.Before(info.JailedUntil) || - selfDel.GetShares().IsNil() || - validator.TokensFromShares(selfDel.GetShares()).TruncateInt().LT(validator.GetMinSelfDelegation()) { - if res != nil && err == nil { - if info.Tombstoned { - return simtypes.NewOperationMsg(msg, true, ""), nil, errors.New("validator should not have been unjailed if validator tombstoned") - } - if ctx.HeaderInfo().Time.Before(info.JailedUntil) { - return simtypes.NewOperationMsg(msg, true, ""), nil, errors.New("validator unjailed while validator still in jail period") - } - if selfDel.GetShares().IsNil() || - validator.TokensFromShares(selfDel.GetShares()).TruncateInt().LT(validator.GetMinSelfDelegation()) { - return simtypes.NewOperationMsg(msg, true, ""), nil, errors.New("validator unjailed even though self-delegation too low") - } - } - // msg failed as expected - return simtypes.NewOperationMsg(msg, false, ""), nil, nil - } - - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(msg), "unable to deliver tx"), nil, errors.New(res.Log) - } - - return simtypes.NewOperationMsg(msg, true, ""), nil, nil - } -} diff --git a/x/staking/CHANGELOG.md b/x/staking/CHANGELOG.md index b185542abed4..24843a45f121 100644 --- a/x/staking/CHANGELOG.md +++ b/x/staking/CHANGELOG.md @@ -34,6 +34,9 @@ Ref: https://keepachangelog.com/en/1.0.0/ * [#19537](https://github.com/cosmos/cosmos-sdk/pull/19537) Changing `MinCommissionRate` in `MsgUpdateParams` now updates the minimum commission rate for all validators. * [#20434](https://github.com/cosmos/cosmos-sdk/pull/20434) Add consensus address to validator query response +* [#21315](https://github.com/cosmos/cosmos-sdk/pull/21315) Create metadata type and add metadata field in validator details proto + * Add parsing of `metadata-profile-pic-uri` in `create-validator` JSON. + * Add cli flag: `metadata-profile-pic-uri` to `edit-validator` cmd. ### Improvements @@ -42,6 +45,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ * [#19277](https://github.com/cosmos/cosmos-sdk/pull/19277) Hooks calls on `SetUnbondingDelegationEntry`, `SetRedelegationEntry`, `Slash` and `RemoveValidator` returns errors instead of logging just like other hooks calls. * [#18636](https://github.com/cosmos/cosmos-sdk/pull/18636) `IterateBondedValidatorsByPower`, `GetDelegatorBonded`, `Delegate`, `Unbond`, `Slash`, `Jail`, `SlashRedelegation`, `ApplyAndReturnValidatorSetUpdates` methods no longer panics on any kind of errors but instead returns appropriate errors. * [#18506](https://github.com/cosmos/cosmos-sdk/pull/18506) Detect the length of the ed25519 pubkey in CreateValidator to prevent panic. +* [#21315](https://github.com/cosmos/cosmos-sdk/pull/21315) Add a `Validate` method to the `Description` type that validates the metadata as well as other description details. ### API Breaking Changes @@ -96,8 +100,11 @@ Ref: https://keepachangelog.com/en/1.0.0/ * [#17335](https://github.com/cosmos/cosmos-sdk/pull/17335) Remove usage of `"cosmossdk.io/x/staking/types".Infraction_*` in favour of `"cosmossdk.io/api/cosmos/staking/v1beta1".Infraction_` in order to remove dependency between modules on staking * [#20295](https://github.com/cosmos/cosmos-sdk/pull/20295) `GetValidatorByConsAddr` now returns the Cosmos SDK `cryptotypes.Pubkey` instead of `cometcrypto.Publickey`. The caller is responsible to translate the returned value to the expected type. * Remove `CmtConsPublicKey()` and `TmConsPublicKey()` from `Validator` interface and as methods on the `Validator` struct. -* [#21480](https://github.com/cosmos/cosmos-sdk/pull/21480) ConsensusKeeper is required to be passed to the keeper. - +* [#21480](https://github.com/cosmos/cosmos-sdk/pull/21480) ConsensusKeeper is required to be passed to the keeper. +* [#21315](https://github.com/cosmos/cosmos-sdk/pull/21315) New struct `Metadata` to store extra validator information. + * New field `Metadata` introduced in `types`: `Description`. + * The signature of `NewDescription` has changed to accept an extra argument of type `Metadata`. + ### State Breaking changes * [#18841](https://github.com/cosmos/cosmos-sdk/pull/18841) In a undelegation or redelegation if the shares being left delegated correspond to less than 1 token (in base denom) the entire delegation gets removed. diff --git a/x/staking/autocli.go b/x/staking/autocli.go index 998e60609f0e..9ac33060c96d 100644 --- a/x/staking/autocli.go +++ b/x/staking/autocli.go @@ -113,7 +113,7 @@ func (am AppModule) AutoCLIOptions() *autocliv1.ModuleOptions { PositionalArgs: []*autocliv1.PositionalArgDescriptor{ {ProtoField: "delegator_addr"}, {ProtoField: "src_validator_addr"}, - {ProtoField: "dst_validator_addr"}, + {ProtoField: "dst_validator_addr", Optional: true}, }, }, { diff --git a/x/staking/client/cli/flags.go b/x/staking/client/cli/flags.go index 61643a04865f..45f3a65e8f38 100644 --- a/x/staking/client/cli/flags.go +++ b/x/staking/client/cli/flags.go @@ -15,12 +15,14 @@ const ( FlagSharesAmount = "shares-amount" FlagSharesFraction = "shares-fraction" - FlagMoniker = "moniker" - FlagEditMoniker = "new-moniker" - FlagIdentity = "identity" - FlagWebsite = "website" - FlagSecurityContact = "security-contact" - FlagDetails = "details" + FlagMoniker = "moniker" + FlagEditMoniker = "new-moniker" + FlagIdentity = "identity" + FlagWebsite = "website" + FlagSecurityContact = "security-contact" + FlagDetails = "details" + FlagMetadataProfilePicUri = "metadata-profile-pic-uri" + FlagMetadataSocialHandleUris = "metadata-social-handle-uris" FlagCommissionRate = "commission-rate" FlagCommissionMaxRate = "commission-max-rate" @@ -89,6 +91,8 @@ func flagSetDescriptionEdit() *flag.FlagSet { fs.String(FlagWebsite, types.DoNotModifyDesc, "The validator's (optional) website") fs.String(FlagSecurityContact, types.DoNotModifyDesc, "The validator's (optional) security contact email") fs.String(FlagDetails, types.DoNotModifyDesc, "The validator's (optional) details") + fs.String(FlagMetadataProfilePicUri, "", "The validator's profile pic uri") + fs.StringArray(FlagMetadataSocialHandleUris, []string{}, "The validator's social handles uris") return fs } diff --git a/x/staking/client/cli/tx.go b/x/staking/client/cli/tx.go index 3e80b30a047b..0e1ba1c396dd 100644 --- a/x/staking/client/cli/tx.go +++ b/x/staking/client/cli/tx.go @@ -72,6 +72,7 @@ Where validator.json contains: "website": "validator's (optional) website", "security": "validator's (optional) security contact email", "details": "validator's (optional) details", + "metadata-profile-pic-uri": "link to validator's (optional) profile picture", "commission-rate": "0.1", "commission-max-rate": "0.2", "commission-max-change-rate": "0.01", @@ -129,7 +130,15 @@ func NewEditValidatorCmd() *cobra.Command { website, _ := cmd.Flags().GetString(FlagWebsite) security, _ := cmd.Flags().GetString(FlagSecurityContact) details, _ := cmd.Flags().GetString(FlagDetails) - description := types.NewDescription(moniker, identity, website, security, details) + profilePicUri, _ := cmd.Flags().GetString(FlagMetadataProfilePicUri) + socialHandlesUris, _ := cmd.Flags().GetStringArray(FlagMetadataSocialHandleUris) + + metadata := types.Metadata{ + ProfilePicUri: profilePicUri, + SocialHandleUris: socialHandlesUris, + } + + description := types.NewDescription(moniker, identity, website, security, details, metadata) var newRate *math.LegacyDec @@ -183,6 +192,7 @@ func newBuildCreateValidatorMsg(clientCtx client.Context, txf tx.Factory, fs *fl val.Website, val.Security, val.Details, + val.Metadata, ) valStr, err := valAc.BytesToString(sdk.ValAddress(valAddr)) @@ -225,6 +235,8 @@ func CreateValidatorMsgFlagSet(ipDefault string) (fs *flag.FlagSet, defaultsDesc fsCreateValidator.String(FlagSecurityContact, "", "The validator's (optional) security contact email") fsCreateValidator.String(FlagDetails, "", "The validator's (optional) details") fsCreateValidator.String(FlagIdentity, "", "The (optional) identity signature (ex. UPort or Keybase)") + fsCreateValidator.String(FlagMetadataProfilePicUri, "", "The validator's profile pic uri") + fsCreateValidator.StringArray(FlagMetadataSocialHandleUris, []string{}, "The validator's social handles uris") fsCreateValidator.AddFlagSet(FlagSetCommissionCreate()) fsCreateValidator.AddFlagSet(FlagSetMinSelfDelegation()) fsCreateValidator.AddFlagSet(FlagSetAmount()) @@ -263,6 +275,7 @@ type TxCreateValidatorConfig struct { SecurityContact string Details string Identity string + Metadata types.Metadata } func PrepareConfigForTxCreateValidator(flagSet *flag.FlagSet, moniker, nodeID, chainID string, valPubKey cryptotypes.PubKey) (TxCreateValidatorConfig, error) { @@ -302,6 +315,14 @@ func PrepareConfigForTxCreateValidator(flagSet *flag.FlagSet, moniker, nodeID, c return c, err } + profilePicUri, err := flagSet.GetString(FlagMetadataProfilePicUri) + if err != nil { + return c, err + } + metadata := types.Metadata{ + ProfilePicUri: profilePicUri, + } + c.Amount, err = flagSet.GetString(FlagAmount) if err != nil { return c, err @@ -338,6 +359,7 @@ func PrepareConfigForTxCreateValidator(flagSet *flag.FlagSet, moniker, nodeID, c c.SecurityContact = securityContact c.Details = details c.Identity = identity + c.Metadata = metadata c.ChainID = chainID c.Moniker = moniker @@ -379,6 +401,7 @@ func BuildCreateValidatorMsg(clientCtx client.Context, config TxCreateValidatorC config.Website, config.SecurityContact, config.Details, + config.Metadata, ) // get the initial validator commission parameters diff --git a/x/staking/client/cli/tx_test.go b/x/staking/client/cli/tx_test.go index 6a39cde2f711..c63bf53ee2b4 100644 --- a/x/staking/client/cli/tx_test.go +++ b/x/staking/client/cli/tx_test.go @@ -149,7 +149,6 @@ func (s *CLITestSuite) TestPrepareConfigForTxCreateValidator() { } for _, tc := range tests { - tc := tc s.Run(tc.name, func() { fs, _ := cli.CreateValidatorMsgFlagSet(ip) fs.String(flags.FlagName, "", "name of private key with which to sign the gentx") @@ -296,7 +295,6 @@ func (s *CLITestSuite) TestNewCreateValidatorCmd() { }, } for _, tc := range testCases { - tc := tc s.Run(tc.name, func() { out, err := clitestutil.ExecTestCLICmd(s.clientCtx, cmd, tc.args) if tc.expectErrMsg != "" { @@ -419,8 +417,6 @@ func (s *CLITestSuite) TestNewEditValidatorCmd() { } for _, tc := range testCases { - tc := tc - s.Run(tc.name, func() { out, err := clitestutil.ExecTestCLICmd(s.clientCtx, cmd, tc.args) if tc.expectErrMsg != "" { diff --git a/x/staking/client/cli/utils.go b/x/staking/client/cli/utils.go index ff22b8876fc4..fc4ed032efc4 100644 --- a/x/staking/client/cli/utils.go +++ b/x/staking/client/cli/utils.go @@ -24,23 +24,26 @@ type validator struct { Website string Security string Details string + Metadata types.Metadata CommissionRates types.CommissionRates MinSelfDelegation math.Int } func parseAndValidateValidatorJSON(cdc codec.Codec, path string) (validator, error) { type internalVal struct { - Amount string `json:"amount"` - PubKey json.RawMessage `json:"pubkey"` - Moniker string `json:"moniker"` - Identity string `json:"identity,omitempty"` - Website string `json:"website,omitempty"` - Security string `json:"security,omitempty"` - Details string `json:"details,omitempty"` - CommissionRate string `json:"commission-rate"` - CommissionMaxRate string `json:"commission-max-rate"` - CommissionMaxChange string `json:"commission-max-change-rate"` - MinSelfDelegation string `json:"min-self-delegation"` + Amount string `json:"amount"` + PubKey json.RawMessage `json:"pubkey"` + Moniker string `json:"moniker"` + Identity string `json:"identity,omitempty"` + Website string `json:"website,omitempty"` + Security string `json:"security,omitempty"` + Details string `json:"details,omitempty"` + MetadataProfilePicUri string `json:"metadata-profile-pic-uri,omitempty"` + MetadataSocialHandlesUris []string `json:"metadata-social-handles-uris,omitempty"` + CommissionRate string `json:"commission-rate"` + CommissionMaxRate string `json:"commission-max-rate"` + CommissionMaxChange string `json:"commission-max-change-rate"` + MinSelfDelegation string `json:"min-self-delegation"` } contents, err := os.ReadFile(path) @@ -87,6 +90,11 @@ func parseAndValidateValidatorJSON(cdc codec.Codec, path string) (validator, err return validator{}, errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "minimum self delegation must be a positive integer") } + metadata, err := buildMetadata(v.MetadataProfilePicUri, v.MetadataSocialHandlesUris) + if err != nil { + return validator{}, err + } + return validator{ Amount: amount, PubKey: pk, @@ -95,6 +103,7 @@ func parseAndValidateValidatorJSON(cdc codec.Codec, path string) (validator, err Website: v.Website, Security: v.Security, Details: v.Details, + Metadata: metadata, CommissionRates: commissionRates, MinSelfDelegation: minSelfDelegation, }, nil @@ -124,3 +133,12 @@ func buildCommissionRates(rateStr, maxRateStr, maxChangeRateStr string) (commiss return commission, nil } + +func buildMetadata(profilePicUri string, socialHandlesUris []string) (metadata types.Metadata, err error) { + metadata.ProfilePicUri = profilePicUri + metadata.SocialHandleUris = socialHandlesUris + if err := metadata.Validate(); err != nil { + return metadata, err + } + return metadata, nil +} diff --git a/x/staking/depinject.go b/x/staking/depinject.go index e1e7a5844960..28012965b4df 100644 --- a/x/staking/depinject.go +++ b/x/staking/depinject.go @@ -17,6 +17,7 @@ import ( "cosmossdk.io/x/staking/types" "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/simsx" "github.com/cosmos/cosmos-sdk/types/module" simtypes "github.com/cosmos/cosmos-sdk/types/simulation" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" @@ -80,7 +81,7 @@ func ProvideModule(in ModuleInputs) ModuleOutputs { in.ConsensusAddressCodec, in.CometInfoService, ) - m := NewAppModule(in.Cdc, k, in.AccountKeeper, in.BankKeeper) + m := NewAppModule(in.Cdc, k) return ModuleOutputs{StakingKeeper: k, Module: m} } @@ -130,20 +131,23 @@ func (AppModule) GenerateGenesisState(simState *module.SimulationState) { simulation.RandomizedGenState(simState) } -// ProposalMsgs returns msgs used for governance proposals for simulations. -func (AppModule) ProposalMsgs(simState module.SimulationState) []simtypes.WeightedProposalMsg { - return simulation.ProposalMsgs() -} - // RegisterStoreDecoder registers a decoder for staking module's types func (am AppModule) RegisterStoreDecoder(sdr simtypes.StoreDecoderRegistry) { sdr[types.StoreKey] = simulation.NewDecodeStore(am.cdc) } -// WeightedOperations returns the all the staking module operations with their respective weights. -func (am AppModule) WeightedOperations(simState module.SimulationState) []simtypes.WeightedOperation { - return simulation.WeightedOperations( - simState.AppParams, simState.Cdc, simState.TxConfig, - am.accountKeeper, am.bankKeeper, am.keeper, - ) +// ProposalMsgsX returns msgs used for governance proposals for simulations. +func (AppModule) ProposalMsgsX(weights simsx.WeightSource, reg simsx.Registry) { + reg.Add(weights.Get("msg_update_params", 100), simulation.MsgUpdateParamsFactory()) +} + +// WeightedOperationsX returns the all the staking module operations with their respective weights. +func (am AppModule) WeightedOperationsX(weights simsx.WeightSource, reg simsx.Registry) { + reg.Add(weights.Get("msg_create_validator", 100), simulation.MsgCreateValidatorFactory(am.keeper)) + reg.Add(weights.Get("msg_delegate", 100), simulation.MsgDelegateFactory(am.keeper)) + reg.Add(weights.Get("msg_undelegate", 100), simulation.MsgUndelegateFactory(am.keeper)) + reg.Add(weights.Get("msg_edit_validator", 5), simulation.MsgEditValidatorFactory(am.keeper)) + reg.Add(weights.Get("msg_begin_redelegate", 100), simulation.MsgBeginRedelegateFactory(am.keeper)) + reg.Add(weights.Get("msg_cancel_unbonding_delegation", 100), simulation.MsgCancelUnbondingDelegationFactory(am.keeper)) + reg.Add(weights.Get("msg_rotate_cons_pubkey", 100), simulation.MsgRotateConsPubKeyFactory(am.keeper)) } diff --git a/x/staking/genesis_test.go b/x/staking/genesis_test.go index ce7eba2ac28b..f7bf349d5a66 100644 --- a/x/staking/genesis_test.go +++ b/x/staking/genesis_test.go @@ -44,8 +44,6 @@ func TestValidateGenesis(t *testing.T) { } for _, tt := range tests { - tt := tt - t.Run(tt.name, func(t *testing.T) { genesisState := types.DefaultGenesisState() tt.mutate(genesisState) diff --git a/x/staking/go.mod b/x/staking/go.mod index 066f8a1f58bc..9c4cdacb1257 100644 --- a/x/staking/go.mod +++ b/x/staking/go.mod @@ -3,10 +3,10 @@ module cosmossdk.io/x/staking go 1.23.1 require ( - cosmossdk.io/api v0.7.5 + cosmossdk.io/api v0.7.6 cosmossdk.io/collections v0.4.0 - cosmossdk.io/core v1.0.0-alpha.2 - cosmossdk.io/core/testing v0.0.0-00010101000000-000000000000 + cosmossdk.io/core v1.0.0-alpha.4 + cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29 cosmossdk.io/depinject v1.0.0 cosmossdk.io/errors v1.0.1 cosmossdk.io/math v1.3.0 @@ -19,14 +19,13 @@ require ( github.com/golang/mock v1.6.0 github.com/golang/protobuf v1.5.4 github.com/grpc-ecosystem/grpc-gateway v1.16.0 - github.com/hashicorp/go-metrics v0.5.3 + github.com/hashicorp/go-metrics v0.5.3 // indirect github.com/spf13/cobra v1.8.1 github.com/spf13/pflag v1.0.5 github.com/stretchr/testify v1.9.0 - google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 - google.golang.org/grpc v1.66.2 + google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 + google.golang.org/grpc v1.67.1 google.golang.org/protobuf v1.34.2 - gotest.tools/v3 v3.5.1 ) require ( @@ -50,7 +49,6 @@ require ( github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect github.com/cometbft/cometbft-db v0.15.0 // indirect github.com/cosmos/btcutil v1.0.5 // indirect - github.com/cosmos/cosmos-db v1.0.3-0.20240911104526-ddc3f09bfc22 // indirect github.com/cosmos/go-bip39 v1.0.0 // indirect github.com/cosmos/gogogateway v1.2.0 // indirect github.com/cosmos/iavl v1.3.0 // indirect @@ -89,7 +87,7 @@ require ( github.com/hashicorp/hcl v1.0.0 // indirect github.com/hashicorp/yamux v0.1.1 // indirect github.com/hdevalence/ed25519consensus v0.2.0 // indirect - github.com/huandu/skiplist v1.2.0 // indirect + github.com/huandu/skiplist v1.2.1 // indirect github.com/iancoleman/strcase v0.3.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jmhodges/levigo v1.0.0 // indirect @@ -111,9 +109,9 @@ require ( github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/client_golang v1.20.3 // indirect + github.com/prometheus/client_golang v1.20.4 // indirect github.com/prometheus/client_model v0.6.1 // indirect - github.com/prometheus/common v0.59.1 // indirect + github.com/prometheus/common v0.60.0 // indirect github.com/prometheus/procfs v0.15.1 // indirect github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect github.com/rogpeppe/go-internal v1.12.0 // indirect @@ -145,7 +143,7 @@ require ( golang.org/x/text v0.18.0 // indirect golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect pgregory.net/rapid v1.1.0 // indirect @@ -165,11 +163,13 @@ require ( ) require ( - cosmossdk.io/schema v0.2.0 // indirect + cosmossdk.io/schema v0.3.1-0.20240930054013-7c6e0388a3f9 // indirect github.com/cockroachdb/fifo v0.0.0-20240606204812-0bbfbd93a7ce // indirect + github.com/cosmos/cosmos-db v1.0.3-0.20240911104526-ddc3f09bfc22 // indirect github.com/google/uuid v1.6.0 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect golang.org/x/exp v0.0.0-20240531132922-fd00a4e0eefc // indirect + gotest.tools/v3 v3.5.1 // indirect ) replace github.com/cosmos/cosmos-sdk => ../../. @@ -178,7 +178,6 @@ replace github.com/cosmos/cosmos-sdk => ../../. replace ( cosmossdk.io/api => ../../api cosmossdk.io/collections => ../../collections - cosmossdk.io/core/testing => ../../core/testing cosmossdk.io/store => ../../store cosmossdk.io/x/bank => ../bank cosmossdk.io/x/tx => ../tx diff --git a/x/staking/go.sum b/x/staking/go.sum index cd6b45de5cf6..7588b565a0d7 100644 --- a/x/staking/go.sum +++ b/x/staking/go.sum @@ -4,8 +4,10 @@ buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.34.2-20240130113600-88e buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.34.2-20240130113600-88ef6483f90f.2/go.mod h1:HqcXMSa5qnNuakaMUo+hWhF51mKbcrZxGl9Vp5EeJXc= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cosmossdk.io/core v1.0.0-alpha.2 h1:epU0Xwces4Rgl5bMhHHkXGaGDcyucNGlC/JDH+Suckg= -cosmossdk.io/core v1.0.0-alpha.2/go.mod h1:abgLjeFLhtuKIYZWSPlVUgQBrKObO7ULV35KYfexE90= +cosmossdk.io/core v1.0.0-alpha.4 h1:9iuroT9ejDYETCsGkzkvs/wAY/5UFl7nCIINFRxyMJY= +cosmossdk.io/core v1.0.0-alpha.4/go.mod h1:3u9cWq1FAVtiiCrDPpo4LhR+9V6k/ycSG4/Y/tREWCY= +cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29 h1:NxxUo0GMJUbIuVg0R70e3cbn9eFTEuMr7ev1AFvypdY= +cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29/go.mod h1:8s2tPeJtSiQuoyPmr2Ag7meikonISO4Fv4MoO8+ORrs= cosmossdk.io/depinject v1.0.0 h1:dQaTu6+O6askNXO06+jyeUAnF2/ssKwrrszP9t5q050= cosmossdk.io/depinject v1.0.0/go.mod h1:zxK/h3HgHoA/eJVtiSsoaRaRA2D5U4cJ5thIG4ssbB8= cosmossdk.io/errors v1.0.1 h1:bzu+Kcr0kS/1DuPBtUFdWjzLqyUuCiyHjyJB6srBV/0= @@ -14,8 +16,8 @@ cosmossdk.io/log v1.4.1 h1:wKdjfDRbDyZRuWa8M+9nuvpVYxrEOwbD/CA8hvhU8QM= cosmossdk.io/log v1.4.1/go.mod h1:k08v0Pyq+gCP6phvdI6RCGhLf/r425UT6Rk/m+o74rU= cosmossdk.io/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE= cosmossdk.io/math v1.3.0/go.mod h1:vnRTxewy+M7BtXBNFybkuhSH4WfedVAAnERHgVFhp3k= -cosmossdk.io/schema v0.2.0 h1:UH5CR1DqUq8yP+5Np8PbvG4YX0zAUsTN2Qk6yThmfMk= -cosmossdk.io/schema v0.2.0/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= +cosmossdk.io/schema v0.3.1-0.20240930054013-7c6e0388a3f9 h1:DmOoS/1PeY6Ih0hAVlJ69kLMUrLV+TCbfICrZtB1vdU= +cosmossdk.io/schema v0.3.1-0.20240930054013-7c6e0388a3f9/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMbk2FiG/kXiLl8BRyzTWDw7gX/Hz7Dd5eDMs= @@ -290,8 +292,8 @@ github.com/hdevalence/ed25519consensus v0.2.0/go.mod h1:w3BHWjwJbFU29IRHL1Iqkw3s github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/huandu/go-assert v1.1.5 h1:fjemmA7sSfYHJD7CUqs9qTwwfdNAx7/j2/ZlHXzNB3c= github.com/huandu/go-assert v1.1.5/go.mod h1:yOLvuqZwmcHIC5rIzrBhT7D3Q9c3GFnd0JrPVhn/06U= -github.com/huandu/skiplist v1.2.0 h1:gox56QD77HzSC0w+Ws3MH3iie755GBJU1OER3h5VsYw= -github.com/huandu/skiplist v1.2.0/go.mod h1:7v3iFjLcSAzO4fN5B8dvebvo/qsfumiLiDXMrPiHF9w= +github.com/huandu/skiplist v1.2.1 h1:dTi93MgjwErA/8idWTzIw4Y1kZsMWx35fmI2c8Rij7w= +github.com/huandu/skiplist v1.2.1/go.mod h1:7v3iFjLcSAzO4fN5B8dvebvo/qsfumiLiDXMrPiHF9w= github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI= github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= @@ -400,8 +402,8 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= -github.com/prometheus/client_golang v1.20.3 h1:oPksm4K8B+Vt35tUhw6GbSNSgVlVSBH0qELP/7u83l4= -github.com/prometheus/client_golang v1.20.3/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_golang v1.20.4 h1:Tgh3Yr67PaOv/uTqloMsCEdeuFTatm5zIq5+qNN23vI= +github.com/prometheus/client_golang v1.20.4/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -410,8 +412,8 @@ github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= -github.com/prometheus/common v0.59.1 h1:LXb1quJHWm1P6wq/U824uxYi4Sg0oGvNeUm1z5dJoX0= -github.com/prometheus/common v0.59.1/go.mod h1:GpWM7dewqmVYcd7SmRaiWVe9SSqjf0UrwnYnpEZNuT0= +github.com/prometheus/common v0.60.0 h1:+V9PAREWNvJMAuJ1x1BaWl9dewMW4YrHZQbx0sJNllA= +github.com/prometheus/common v0.60.0/go.mod h1:h0LYf1R1deLSKtD4Vdg8gy4RuOvENW2J/h19V5NADQw= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/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= @@ -634,10 +636,10 @@ google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEY google.golang.org/genproto v0.0.0-20220314164441-57ef72a4c106/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E= google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de h1:F6qOa9AZTYJXOUEr4jDysRDLrm4PHePlge4v4TGAlxY= google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:VUhTRKeHn9wwcdrk73nvdC9gF178Tzhmt/qyaFcPLSo= -google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 h1:+rdxYoE3E5htTEWIe15GlN6IfvbURM//Jt0mmkmm6ZU= -google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117/go.mod h1:OimBR/bc1wPO9iV4NC2bpyjy3VnAwZh5EBPQdtaE5oo= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:pPJltXNxVzT4pK9yD8vR9X75DaWYYmLGMsEvBfFQZzQ= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= +google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 h1:wKguEg1hsxI2/L3hUYrpo1RVi48K+uTyzKqprwLXsb8= +google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142/go.mod h1:d6be+8HhtEtucleCbxpPW9PA9XwISACu8nvpPqF0BVo= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f h1:cUMEy+8oS78BWIH9OWazBkzbr090Od9tWBNtZHkOhf0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= @@ -648,8 +650,8 @@ google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= -google.golang.org/grpc v1.66.2 h1:3QdXkuq3Bkh7w+ywLdLvM56cmGvQHUMZpiCzt6Rqaoo= -google.golang.org/grpc v1.66.2/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y= +google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E= +google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= 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= diff --git a/x/staking/keeper/abci.go b/x/staking/keeper/abci.go index dc14285ccf68..79bfbf5595f6 100644 --- a/x/staking/keeper/abci.go +++ b/x/staking/keeper/abci.go @@ -13,5 +13,6 @@ import ( func (k *Keeper) EndBlocker(ctx context.Context) ([]appmodule.ValidatorUpdate, error) { start := telemetry.Now() defer telemetry.ModuleMeasureSince(types.ModuleName, start, telemetry.MetricKeyEndBlocker) + return k.BlockValidatorUpdates(ctx) } diff --git a/x/staking/keeper/cons_pubkey.go b/x/staking/keeper/cons_pubkey.go index e1938597fa7c..d60d4628b959 100644 --- a/x/staking/keeper/cons_pubkey.go +++ b/x/staking/keeper/cons_pubkey.go @@ -258,8 +258,7 @@ func (k Keeper) GetBlockConsPubKeyRotationHistory(ctx context.Context) ([]types. if err != nil { return nil, err } - defer iterator.Close() - + // iterator would be closed in the CollectValues return indexes.CollectValues(ctx, k.RotationHistory, iterator) } diff --git a/x/staking/keeper/grpc_query.go b/x/staking/keeper/grpc_query.go index 99030babfbeb..e55671f34c9e 100644 --- a/x/staking/keeper/grpc_query.go +++ b/x/staking/keeper/grpc_query.go @@ -411,7 +411,7 @@ func (k Querier) DelegatorUnbondingDelegations(ctx context.Context, req *types.Q } // HistoricalInfo queries the historical info for given height -func (k Querier) HistoricalInfo(ctx context.Context, req *types.QueryHistoricalInfoRequest) (*types.QueryHistoricalInfoResponse, error) { // nolint:staticcheck // SA1019: deprecated endpoint +func (k Querier) HistoricalInfo(ctx context.Context, req *types.QueryHistoricalInfoRequest) (*types.QueryHistoricalInfoResponse, error) { //nolint:staticcheck // SA1019: deprecated endpoint if req == nil { return nil, status.Error(codes.InvalidArgument, "empty request") } diff --git a/x/staking/keeper/keeper_test.go b/x/staking/keeper/keeper_test.go index 92561bc6e7f3..24e0f1bd7437 100644 --- a/x/staking/keeper/keeper_test.go +++ b/x/staking/keeper/keeper_test.go @@ -481,7 +481,7 @@ func (s *KeeperTestSuite) TestValidatorsMigrationToColls() { // legacy Set method s.ctx.KVStore(s.key).Set(getValidatorKey(valAddrs[i]), valBz) }, - "d8acdcf8b7c8e17f3e83f0a4c293f89ad619a5dcb14d232911ccc5da15653177", + "55565aebbb67e1de08d0f17634ad168c68eae74f5cc9074e3a1ec4d1fbff16e5", ) s.Require().NoError(err) @@ -507,7 +507,7 @@ func (s *KeeperTestSuite) TestValidatorsMigrationToColls() { err := s.stakingKeeper.SetValidator(s.ctx, val) s.Require().NoError(err) }, - "d8acdcf8b7c8e17f3e83f0a4c293f89ad619a5dcb14d232911ccc5da15653177", + "55565aebbb67e1de08d0f17634ad168c68eae74f5cc9074e3a1ec4d1fbff16e5", ) s.Require().NoError(err) } diff --git a/x/staking/keeper/msg_server.go b/x/staking/keeper/msg_server.go index fa7cd6a6c0bf..272932c494fb 100644 --- a/x/staking/keeper/msg_server.go +++ b/x/staking/keeper/msg_server.go @@ -9,7 +9,6 @@ import ( "strconv" "time" - "github.com/hashicorp/go-metrics" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" @@ -21,7 +20,6 @@ import ( "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" - "github.com/cosmos/cosmos-sdk/telemetry" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" ) @@ -111,7 +109,7 @@ func (k msgServer) CreateValidator(ctx context.Context, msg *types.MsgCreateVali ) } - if _, err := msg.Description.EnsureLength(); err != nil { + if _, err := msg.Description.Validate(); err != nil { return nil, err } @@ -178,7 +176,7 @@ func (k msgServer) EditValidator(ctx context.Context, msg *types.MsgEditValidato return nil, sdkerrors.ErrInvalidAddress.Wrapf("invalid validator address: %s", err) } - if msg.Description == (types.Description{}) { + if msg.Description.IsEmpty() { return nil, errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "empty description") } @@ -301,17 +299,6 @@ func (k msgServer) Delegate(ctx context.Context, msg *types.MsgDelegate) (*types return nil, err } - if msg.Amount.Amount.IsInt64() { - defer func() { - telemetry.IncrCounter(1, types.ModuleName, "delegate") - telemetry.SetGaugeWithLabels( - []string{"tx", "msg", sdk.MsgTypeURL(msg)}, - float32(msg.Amount.Amount.Int64()), - []metrics.Label{telemetry.NewLabel("denom", msg.Amount.Denom)}, - ) - }() - } - if err := k.EventService.EventManager(ctx).EmitKV( types.EventTypeDelegate, event.NewAttribute(types.AttributeKeyValidator, msg.ValidatorAddress), @@ -374,17 +361,6 @@ func (k msgServer) BeginRedelegate(ctx context.Context, msg *types.MsgBeginRedel return nil, err } - if msg.Amount.Amount.IsInt64() { - defer func() { - telemetry.IncrCounter(1, types.ModuleName, "redelegate") - telemetry.SetGaugeWithLabels( - []string{"tx", "msg", sdk.MsgTypeURL(msg)}, - float32(msg.Amount.Amount.Int64()), - []metrics.Label{telemetry.NewLabel("denom", msg.Amount.Denom)}, - ) - }() - } - if err := k.EventService.EventManager(ctx).EmitKV( types.EventTypeRedelegate, event.NewAttribute(types.AttributeKeySrcValidator, msg.ValidatorSrcAddress), @@ -444,17 +420,6 @@ func (k msgServer) Undelegate(ctx context.Context, msg *types.MsgUndelegate) (*t undelegatedCoin := sdk.NewCoin(msg.Amount.Denom, undelegatedAmt) - if msg.Amount.Amount.IsInt64() { - defer func() { - telemetry.IncrCounter(1, types.ModuleName, "undelegate") - telemetry.SetGaugeWithLabels( - []string{"tx", "msg", sdk.MsgTypeURL(msg)}, - float32(msg.Amount.Amount.Int64()), - []metrics.Label{telemetry.NewLabel("denom", msg.Amount.Denom)}, - ) - }() - } - if err := k.EventService.EventManager(ctx).EmitKV( types.EventTypeUnbond, event.NewAttribute(types.AttributeKeyValidator, msg.ValidatorAddress), diff --git a/x/staking/keeper/msg_server_test.go b/x/staking/keeper/msg_server_test.go index f436b2ebda00..b5d92d62f535 100644 --- a/x/staking/keeper/msg_server_test.go +++ b/x/staking/keeper/msg_server_test.go @@ -314,7 +314,6 @@ func (s *KeeperTestSuite) TestMsgCreateValidator() { }, } for _, tc := range testCases { - tc := tc s.T().Run(tc.name, func(t *testing.T) { if tc.expPanic { require.PanicsWithValue(tc.expPanicMsg, func() { @@ -496,7 +495,6 @@ func (s *KeeperTestSuite) TestMsgEditValidator() { }, } for _, tc := range testCases { - tc := tc s.T().Run(tc.name, func(t *testing.T) { _, err := msgServer.EditValidator(tc.ctx, tc.input) if tc.expErr { @@ -614,7 +612,6 @@ func (s *KeeperTestSuite) TestMsgDelegate() { } for _, tc := range testCases { - tc := tc s.T().Run(tc.name, func(t *testing.T) { _, err := msgServer.Delegate(ctx, tc.input) if tc.expErr { @@ -782,7 +779,6 @@ func (s *KeeperTestSuite) TestMsgBeginRedelegate() { } for _, tc := range testCases { - tc := tc s.T().Run(tc.name, func(t *testing.T) { _, err := msgServer.BeginRedelegate(ctx, tc.input) if tc.expErr { @@ -906,7 +902,6 @@ func (s *KeeperTestSuite) TestMsgUndelegate() { } for _, tc := range testCases { - tc := tc s.T().Run(tc.name, func(t *testing.T) { _, err := msgServer.Undelegate(ctx, tc.input) if tc.expErr { @@ -1068,7 +1063,6 @@ func (s *KeeperTestSuite) TestMsgCancelUnbondingDelegation() { } for _, tc := range testCases { - tc := tc s.T().Run(tc.name, func(t *testing.T) { _, err := msgServer.CancelUnbondingDelegation(ctx, tc.input) if tc.expErr { @@ -1233,7 +1227,6 @@ func (s *KeeperTestSuite) TestMsgUpdateParams() { } for _, tc := range testCases { - tc := tc s.T().Run(tc.name, func(t *testing.T) { _, err := msgServer.UpdateParams(ctx, tc.input) if tc.expErrMsg != "" { diff --git a/x/staking/module.go b/x/staking/module.go index cddb3ba4c4d2..52b5313ed15b 100644 --- a/x/staking/module.go +++ b/x/staking/module.go @@ -43,24 +43,15 @@ var ( // AppModule implements an application module for the staking module. type AppModule struct { - cdc codec.Codec - keeper *keeper.Keeper - accountKeeper types.AccountKeeper - bankKeeper types.BankKeeper + cdc codec.Codec + keeper *keeper.Keeper } // NewAppModule creates a new AppModule object -func NewAppModule( - cdc codec.Codec, - keeper *keeper.Keeper, - ak types.AccountKeeper, - bk types.BankKeeper, -) AppModule { +func NewAppModule(cdc codec.Codec, keeper *keeper.Keeper) AppModule { return AppModule{ - cdc: cdc, - keeper: keeper, - accountKeeper: ak, - bankKeeper: bk, + cdc: cdc, + keeper: keeper, } } diff --git a/x/staking/proto/buf.lock b/x/staking/proto/buf.lock index 3a2b87c1a666..3ad9de72f05b 100644 --- a/x/staking/proto/buf.lock +++ b/x/staking/proto/buf.lock @@ -11,6 +11,11 @@ deps: repository: cosmos-proto commit: 04467658e59e44bbb22fe568206e1f70 digest: shake256:73a640bd60e0c523b0f8237ff34eab67c45a38b64bbbde1d80224819d272dbf316ac183526bd245f994af6608b025f5130483d0133c5edd385531326b5990466 + - remote: buf.build + owner: cosmos + repository: cosmos-sdk + commit: 05419252bcc241ea8023acf1ed4cadc5 + digest: shake256:1e54a48c19a8b59d35e0a7efa76402939f515f2d8005df099856f24c37c20a52800308f025abb8cffcd014d437b49707388aaca4865d9d063d8f25d5d4eb77d5 - remote: buf.build owner: cosmos repository: gogo-proto @@ -19,5 +24,15 @@ deps: - remote: buf.build owner: googleapis repository: googleapis - commit: 7e6f6e774e29406da95bd61cdcdbc8bc - digest: shake256:fe43dd2265ea0c07d76bd925eeba612667cf4c948d2ce53d6e367e1b4b3cb5fa69a51e6acb1a6a50d32f894f054a35e6c0406f6808a483f2752e10c866ffbf73 + commit: 8bc2c51e08c447cd8886cdea48a73e14 + digest: shake256:a969155953a5cedc5b2df5b42c368f2bc66ff8ce1804bc96e0f14ff2ee8a893687963058909df844d1643cdbc98ff099d2daa6bc9f9f5b8886c49afdc60e19af + - remote: buf.build + owner: protocolbuffers + repository: wellknowntypes + commit: 657250e6a39648cbb169d079a60bd9ba + digest: shake256:00de25001b8dd2e29d85fc4bcc3ede7aed886d76d67f5e0f7a9b320b90f871d3eb73507d50818d823a0512f3f8db77a11c043685528403e31ff3fef18323a9fb + - remote: buf.build + owner: tendermint + repository: tendermint + commit: 33ed361a90514289beabf3189e1d7665 + digest: shake256:038267e06294714fd883610626554b04a127b576b4e253befb4206cb72d5d3c1eeccacd4b9ec8e3fb891f7c14e1cb0f770c077d2989638995b0a61c85afedb1d diff --git a/x/staking/proto/cosmos/staking/v1beta1/query.proto b/x/staking/proto/cosmos/staking/v1beta1/query.proto index 863b598179ab..e52eb970d0e9 100644 --- a/x/staking/proto/cosmos/staking/v1beta1/query.proto +++ b/x/staking/proto/cosmos/staking/v1beta1/query.proto @@ -304,10 +304,10 @@ message QueryRedelegationsRequest { string delegator_addr = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"]; // src_validator_addr defines the validator address to redelegate from. - string src_validator_addr = 2 [(cosmos_proto.scalar) = "cosmos.AddressString"]; + string src_validator_addr = 2 [(cosmos_proto.scalar) = "cosmos.ValidatorAddressString"]; // dst_validator_addr defines the validator address to redelegate to. - string dst_validator_addr = 3 [(cosmos_proto.scalar) = "cosmos.AddressString"]; + string dst_validator_addr = 3 [(cosmos_proto.scalar) = "cosmos.ValidatorAddressString"]; // pagination defines an optional pagination for the request. cosmos.base.query.v1beta1.PageRequest pagination = 4; diff --git a/x/staking/proto/cosmos/staking/v1beta1/staking.proto b/x/staking/proto/cosmos/staking/v1beta1/staking.proto index 8b8709322305..b6dd5fcbff78 100644 --- a/x/staking/proto/cosmos/staking/v1beta1/staking.proto +++ b/x/staking/proto/cosmos/staking/v1beta1/staking.proto @@ -1,17 +1,16 @@ syntax = "proto3"; package cosmos.staking.v1beta1; +import "amino/amino.proto"; +import "cometbft/abci/v1/types.proto"; +import "cometbft/types/v1/types.proto"; +import "cosmos/base/v1beta1/coin.proto"; +import "cosmos_proto/cosmos.proto"; import "gogoproto/gogo.proto"; import "google/protobuf/any.proto"; import "google/protobuf/duration.proto"; import "google/protobuf/timestamp.proto"; -import "cosmos_proto/cosmos.proto"; -import "cosmos/base/v1beta1/coin.proto"; -import "amino/amino.proto"; -import "cometbft/types/v1/types.proto"; -import "cometbft/abci/v1/types.proto"; - option go_package = "cosmossdk.io/x/staking/types"; // HistoricalInfo contains header and validator information for a given block. @@ -79,6 +78,19 @@ message Description { string security_contact = 4; // details define other optional details. string details = 5; + // metadata defines extra information about the validator. + Metadata metadata = 6 [(gogoproto.nullable) = false, (amino.dont_omitempty) = true]; +} + +// Metadata defines extra information about the validator. +message Metadata { + option (gogoproto.equal) = true; + + // profile_pic_uri defines a link to the validator profile picture. + string profile_pic_uri = 1; + + // social_handle_uris defines a string array of uris to the validator's social handles. + repeated string social_handle_uris = 2; } // Validator defines a validator, together with the total amount of the @@ -221,7 +233,8 @@ message UnbondingDelegation { string validator_address = 2 [(cosmos_proto.scalar) = "cosmos.ValidatorAddressString"]; // entries are the unbonding delegation entries. repeated UnbondingDelegationEntry entries = 3 - [(gogoproto.nullable) = false, (amino.dont_omitempty) = true]; // unbonding delegation entries + [(gogoproto.nullable) = false, + (amino.dont_omitempty) = true]; // unbonding delegation entries } // UnbondingDelegationEntry defines an unbonding object with relevant metadata. @@ -294,7 +307,8 @@ message Redelegation { string validator_dst_address = 3 [(cosmos_proto.scalar) = "cosmos.ValidatorAddressString"]; // entries are the redelegation entries. repeated RedelegationEntry entries = 4 - [(gogoproto.nullable) = false, (amino.dont_omitempty) = true]; // redelegation entries + [(gogoproto.nullable) = false, + (amino.dont_omitempty) = true]; // redelegation entries } // Params defines the parameters for the x/staking module. diff --git a/x/staking/simulation/decoder_test.go b/x/staking/simulation/decoder_test.go index 897219b86cce..cfdf2adf19a1 100644 --- a/x/staking/simulation/decoder_test.go +++ b/x/staking/simulation/decoder_test.go @@ -46,7 +46,6 @@ func TestDecodeStore(t *testing.T) { {"other", ""}, } for i, tt := range tests { - i, tt := i, tt t.Run(tt.name, func(t *testing.T) { switch i { case len(tests) - 1: diff --git a/x/staking/simulation/genesis.go b/x/staking/simulation/genesis.go index da5f694941d3..9808c3f43086 100644 --- a/x/staking/simulation/genesis.go +++ b/x/staking/simulation/genesis.go @@ -1,8 +1,6 @@ package simulation import ( - "encoding/json" - "fmt" "math/rand" "time" @@ -108,11 +106,5 @@ func RandomizedGenState(simState *module.SimulationState) { } stakingGenesis := types.NewGenesisState(params, validators, delegations) - - bz, err := json.MarshalIndent(&stakingGenesis.Params, "", " ") - if err != nil { - panic(err) - } - fmt.Printf("Selected randomly generated staking parameters:\n%s\n", bz) simState.GenState[types.ModuleName] = simState.Cdc.MustMarshalJSON(stakingGenesis) } diff --git a/x/staking/simulation/genesis_test.go b/x/staking/simulation/genesis_test.go index d6350a037b28..d07553c0c156 100644 --- a/x/staking/simulation/genesis_test.go +++ b/x/staking/simulation/genesis_test.go @@ -109,8 +109,6 @@ func TestRandomizedGenState1(t *testing.T) { } for _, tt := range tests { - tt := tt - require.Panicsf(t, func() { simulation.RandomizedGenState(&tt.simState) }, tt.panicMsg) } } diff --git a/x/staking/simulation/msg_factory.go b/x/staking/simulation/msg_factory.go new file mode 100644 index 000000000000..49aff2505298 --- /dev/null +++ b/x/staking/simulation/msg_factory.go @@ -0,0 +1,392 @@ +package simulation + +import ( + "context" + "slices" + "time" + + "cosmossdk.io/math" + "cosmossdk.io/x/staking/keeper" + "cosmossdk.io/x/staking/types" + + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" + "github.com/cosmos/cosmos-sdk/simsx" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +func MsgCreateValidatorFactory(k *keeper.Keeper) simsx.SimMsgFactoryFn[*types.MsgCreateValidator] { + return func(ctx context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter) ([]simsx.SimAccount, *types.MsgCreateValidator) { + r := testData.Rand() + withoutValidators := simsx.SimAccountFilterFn(func(a simsx.SimAccount) bool { + _, err := k.GetValidator(ctx, sdk.ValAddress(a.Address)) + return err != nil + }) + withoutConsAddrUsed := simsx.SimAccountFilterFn(func(a simsx.SimAccount) bool { + consPubKey := sdk.GetConsAddress(a.ConsKey.PubKey()) + _, err := k.GetValidatorByConsAddr(ctx, consPubKey) + return err != nil + }) + bondDenom := must(k.BondDenom(ctx)) + valOper := testData.AnyAccount(reporter, withoutValidators, withoutConsAddrUsed, simsx.WithDenomBalance(bondDenom)) + if reporter.IsSkipped() { + return nil, nil + } + + newPubKey := valOper.ConsKey.PubKey() + assertKeyUnused(ctx, reporter, k, newPubKey) + if reporter.IsSkipped() { + return nil, nil + } + + selfDelegation := valOper.LiquidBalance().RandSubsetCoin(reporter, bondDenom) + + description := types.NewDescription( + r.StringN(10), + r.StringN(10), + r.StringN(10), + r.StringN(10), + r.StringN(10), + types.Metadata{ + ProfilePicUri: RandURIOfHostLength(r.Rand, 10), + SocialHandleUris: RandSocialHandleURIs(r.Rand, 2, 10), + }, + ) + + maxCommission := math.LegacyNewDecWithPrec(int64(r.IntInRange(0, 100)), 2) + commission := types.NewCommissionRates( + r.DecN(maxCommission), + maxCommission, + r.DecN(maxCommission), + ) + + addr := must(k.ValidatorAddressCodec().BytesToString(valOper.Address)) + msg, err := types.NewMsgCreateValidator(addr, newPubKey, selfDelegation, description, commission, math.OneInt()) + if err != nil { + reporter.Skip(err.Error()) + return nil, nil + } + + return []simsx.SimAccount{valOper}, msg + } +} + +func MsgDelegateFactory(k *keeper.Keeper) simsx.SimMsgFactoryFn[*types.MsgDelegate] { + return func(ctx context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter) ([]simsx.SimAccount, *types.MsgDelegate) { + r := testData.Rand() + bondDenom := must(k.BondDenom(ctx)) + val := randomValidator(ctx, reporter, k, r) + if reporter.IsSkipped() { + return nil, nil + } + + if val.InvalidExRate() { + reporter.Skip("validator's invalid exchange rate") + return nil, nil + } + sender := testData.AnyAccount(reporter) + delegation := sender.LiquidBalance().RandSubsetCoin(reporter, bondDenom) + return []simsx.SimAccount{sender}, types.NewMsgDelegate(sender.AddressBech32, val.GetOperator(), delegation) + } +} + +func MsgUndelegateFactory(k *keeper.Keeper) simsx.SimMsgFactoryFn[*types.MsgUndelegate] { + return func(ctx context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter) ([]simsx.SimAccount, *types.MsgUndelegate) { + r := testData.Rand() + bondDenom := must(k.BondDenom(ctx)) + val := randomValidator(ctx, reporter, k, r) + if reporter.IsSkipped() { + return nil, nil + } + + // select delegator and amount for undelegate + valAddr := must(k.ValidatorAddressCodec().StringToBytes(val.GetOperator())) + delegations := must(k.GetValidatorDelegations(ctx, valAddr)) + if delegations == nil { + reporter.Skip("no delegation entries") + return nil, nil + } + // get random delegator from validator + delegation := delegations[r.Intn(len(delegations))] + delAddr := delegation.GetDelegatorAddr() + delegator := testData.GetAccount(reporter, delAddr) + + if hasMaxUD := must(k.HasMaxUnbondingDelegationEntries(ctx, delegator.Address, valAddr)); hasMaxUD { + reporter.Skipf("max unbodings") + return nil, nil + } + + totalBond := val.TokensFromShares(delegation.GetShares()).TruncateInt() + if !totalBond.IsPositive() { + reporter.Skip("total bond is negative") + return nil, nil + } + + unbondAmt := must(r.PositiveSDKIntn(totalBond)) + msg := types.NewMsgUndelegate(delAddr, val.GetOperator(), sdk.NewCoin(bondDenom, unbondAmt)) + return []simsx.SimAccount{delegator}, msg + } +} + +func MsgEditValidatorFactory(k *keeper.Keeper) simsx.SimMsgFactoryFn[*types.MsgEditValidator] { + return func(ctx context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter) ([]simsx.SimAccount, *types.MsgEditValidator) { + r := testData.Rand() + val := randomValidator(ctx, reporter, k, r) + if reporter.IsSkipped() { + return nil, nil + } + + newCommissionRate := r.DecN(val.Commission.MaxRate) + if err := val.Commission.ValidateNewRate(newCommissionRate, simsx.BlockTime(ctx)); err != nil { + // skip as the commission is invalid + reporter.Skip("invalid commission rate") + return nil, nil + } + valOpAddrBz := must(k.ValidatorAddressCodec().StringToBytes(val.GetOperator())) + valOper := testData.GetAccountbyAccAddr(reporter, valOpAddrBz) + d := types.NewDescription(r.StringN(10), r.StringN(10), r.StringN(10), r.StringN(10), r.StringN(10), types.Metadata{ + ProfilePicUri: RandURIOfHostLength(r.Rand, 10), + SocialHandleUris: RandSocialHandleURIs(r.Rand, 2, 10), + }) + + msg := types.NewMsgEditValidator(val.GetOperator(), d, &newCommissionRate, nil) + return []simsx.SimAccount{valOper}, msg + } +} + +func MsgBeginRedelegateFactory(k *keeper.Keeper) simsx.SimMsgFactoryFn[*types.MsgBeginRedelegate] { + return func(ctx context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter) ([]simsx.SimAccount, *types.MsgBeginRedelegate) { + bondDenom := must(k.BondDenom(ctx)) + if !testData.IsSendEnabledDenom(bondDenom) { + reporter.Skip("bond denom send not enabled") + return nil, nil + } + + r := testData.Rand() + // select random validator as src + vals := must(k.GetAllValidators(ctx)) + if len(vals) < 2 { + reporter.Skip("insufficient number of validators") + return nil, nil + } + srcVal := simsx.OneOf(r, vals) + srcValOpAddrBz := must(k.ValidatorAddressCodec().StringToBytes(srcVal.GetOperator())) + delegations := must(k.GetValidatorDelegations(ctx, srcValOpAddrBz)) + if delegations == nil { + reporter.Skip("no delegations") + return nil, nil + } + // get random delegator from src validator + delegation := simsx.OneOf(r, delegations) + totalBond := srcVal.TokensFromShares(delegation.GetShares()).TruncateInt() + if !totalBond.IsPositive() { + reporter.Skip("total bond is negative") + return nil, nil + } + redAmount, err := r.PositiveSDKIntn(totalBond) + if err != nil || redAmount.IsZero() { + reporter.Skip("unable to generate positive amount") + return nil, nil + } + + // check if the shares truncate to zero + shares := must(srcVal.SharesFromTokens(redAmount)) + if srcVal.TokensFromShares(shares).TruncateInt().IsZero() { + reporter.Skip("shares truncate to zero") + return nil, nil + } + + // pick a random delegator + delAddr := delegation.GetDelegatorAddr() + delAddrBz := must(testData.AddressCodec().StringToBytes(delAddr)) + if hasRecRedel := must(k.HasReceivingRedelegation(ctx, delAddrBz, srcValOpAddrBz)); hasRecRedel { + reporter.Skip("receiving redelegation is not allowed") + return nil, nil + } + delegator := testData.GetAccountbyAccAddr(reporter, delAddrBz) + if reporter.IsSkipped() { + return nil, nil + } + + // get random destination validator + destVal := simsx.OneOf(r, vals) + if srcVal.Equal(&destVal) { + destVal = simsx.OneOf(r, slices.DeleteFunc(vals, func(v types.Validator) bool { return srcVal.Equal(&v) })) + } + if destVal.InvalidExRate() { + reporter.Skip("invalid delegation rate") + return nil, nil + } + + destAddrBz := must(k.ValidatorAddressCodec().StringToBytes(destVal.GetOperator())) + if hasMaxRedel := must(k.HasMaxRedelegationEntries(ctx, delAddrBz, srcValOpAddrBz, destAddrBz)); hasMaxRedel { + reporter.Skip("maximum redelegation entries reached") + return nil, nil + } + + msg := types.NewMsgBeginRedelegate( + delAddr, srcVal.GetOperator(), destVal.GetOperator(), + sdk.NewCoin(bondDenom, redAmount), + ) + return []simsx.SimAccount{delegator}, msg + } +} + +func MsgCancelUnbondingDelegationFactory(k *keeper.Keeper) simsx.SimMsgFactoryFn[*types.MsgCancelUnbondingDelegation] { + return func(ctx context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter) ([]simsx.SimAccount, *types.MsgCancelUnbondingDelegation) { + r := testData.Rand() + val := randomValidator(ctx, reporter, k, r) + if reporter.IsSkipped() { + return nil, nil + } + if val.IsJailed() || val.InvalidExRate() { + reporter.Skip("validator is jailed") + return nil, nil + } + valOpAddrBz := must(k.ValidatorAddressCodec().StringToBytes(val.GetOperator())) + valOper := testData.GetAccountbyAccAddr(reporter, valOpAddrBz) + unbondingDelegation, err := k.GetUnbondingDelegation(ctx, valOper.Address, valOpAddrBz) + if err != nil { + reporter.Skip("no unbonding delegation") + return nil, nil + } + + // This is a temporary fix to make staking simulation pass. We should fetch + // the first unbondingDelegationEntry that matches the creationHeight, because + // currently the staking msgServer chooses the first unbondingDelegationEntry + // with the matching creationHeight. + // + // ref: https://github.com/cosmos/cosmos-sdk/issues/12932 + creationHeight := unbondingDelegation.Entries[r.Intn(len(unbondingDelegation.Entries))].CreationHeight + + var unbondingDelegationEntry types.UnbondingDelegationEntry + for _, entry := range unbondingDelegation.Entries { + if entry.CreationHeight == creationHeight { + unbondingDelegationEntry = entry + break + } + } + if unbondingDelegationEntry.CompletionTime.Before(simsx.BlockTime(ctx)) { + reporter.Skip("unbonding delegation is already processed") + return nil, nil + } + + if !unbondingDelegationEntry.Balance.IsPositive() { + reporter.Skip("delegator receiving balance is negative") + return nil, nil + } + cancelBondAmt := r.Amount(unbondingDelegationEntry.Balance) + if cancelBondAmt.IsZero() { + reporter.Skip("cancelBondAmt amount is zero") + return nil, nil + } + + msg := types.NewMsgCancelUnbondingDelegation( + valOper.AddressBech32, + val.GetOperator(), + unbondingDelegationEntry.CreationHeight, + sdk.NewCoin(must(k.BondDenom(ctx)), cancelBondAmt), + ) + + return []simsx.SimAccount{valOper}, msg + } +} + +func MsgRotateConsPubKeyFactory(k *keeper.Keeper) simsx.SimMsgFactoryFn[*types.MsgRotateConsPubKey] { + return func(ctx context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter) ([]simsx.SimAccount, *types.MsgRotateConsPubKey) { + r := testData.Rand() + val := randomValidator(ctx, reporter, k, r) + if reporter.IsSkipped() { + return nil, nil + } + if val.Status != types.Bonded || val.ConsensusPower(sdk.DefaultPowerReduction) == 0 { + reporter.Skip("validator not bonded.") + return nil, nil + } + valOpAddrBz := must(k.ValidatorAddressCodec().StringToBytes(val.GetOperator())) + valOper := testData.GetAccountbyAccAddr(reporter, valOpAddrBz) + otherAccount := testData.AnyAccount(reporter, simsx.ExcludeAddresses(valOper.AddressBech32)) + + consAddress := must(k.ConsensusAddressCodec().BytesToString(must(val.GetConsAddr()))) + accAddress := must(k.ConsensusAddressCodec().BytesToString(otherAccount.ConsKey.PubKey().Address())) + if consAddress == accAddress { + reporter.Skip("new pubkey and current pubkey should be different") + return nil, nil + } + if !valOper.LiquidBalance().BlockAmount(must(k.Params.Get(ctx)).KeyRotationFee) { + reporter.Skip("not enough balance to pay for key rotation fee") + return nil, nil + } + if err := k.ExceedsMaxRotations(ctx, valOpAddrBz); err != nil { + reporter.Skip("rotations limit reached within unbonding period") + return nil, nil + } + // check whether the new cons key associated with another validator + newConsAddr := sdk.ConsAddress(otherAccount.ConsKey.PubKey().Address()) + + if _, err := k.GetValidatorByConsAddr(ctx, newConsAddr); err == nil { + reporter.Skip("cons key already used") + return nil, nil + } + msg := must(types.NewMsgRotateConsPubKey(val.GetOperator(), otherAccount.ConsKey.PubKey())) + + // check if there's another key rotation for this same key in the same block + for _, r := range must(k.GetBlockConsPubKeyRotationHistory(ctx)) { + if r.NewConsPubkey.Compare(msg.NewPubkey) == 0 { + reporter.Skip("cons key already used in this block") + return nil, nil + } + } + return []simsx.SimAccount{valOper}, msg + } +} + +// MsgUpdateParamsFactory creates a gov proposal for param updates +func MsgUpdateParamsFactory() simsx.SimMsgFactoryFn[*types.MsgUpdateParams] { + return func(_ context.Context, testData *simsx.ChainDataSource, reporter simsx.SimulationReporter) ([]simsx.SimAccount, *types.MsgUpdateParams) { + r := testData.Rand() + params := types.DefaultParams() + // do not modify denom or staking will break + params.HistoricalEntries = r.Uint32InRange(0, 1000) + params.MaxEntries = r.Uint32InRange(1, 1000) + params.MaxValidators = r.Uint32InRange(1, 1000) + params.UnbondingTime = time.Duration(r.Timestamp().UnixNano()) + // modifying commission rate can cause issues for proposals within the same block + // params.MinCommissionRate = r.DecN(sdkmath.LegacyNewDec(1)) + + return nil, &types.MsgUpdateParams{ + Authority: testData.ModuleAccountAddress(reporter, "gov"), + Params: params, + } + } +} + +func randomValidator(ctx context.Context, reporter simsx.SimulationReporter, k *keeper.Keeper, r *simsx.XRand) types.Validator { + vals, err := k.GetAllValidators(ctx) + if err != nil || len(vals) == 0 { + reporter.Skipf("unable to get validators or empty list: %s", err) + return types.Validator{} + } + return simsx.OneOf(r, vals) +} + +// skips execution if there's another key rotation for the same key in the same block +func assertKeyUnused(ctx context.Context, reporter simsx.SimulationReporter, k *keeper.Keeper, newPubKey cryptotypes.PubKey) { + allRotations, err := k.GetBlockConsPubKeyRotationHistory(ctx) + if err != nil { + reporter.Skipf("cannot get block cons key rotation history: %s", err.Error()) + return + } + for _, r := range allRotations { + if r.NewConsPubkey.Compare(newPubKey) != 0 { + reporter.Skip("cons key already used in this block") + return + } + } +} + +func must[T any](r T, err error) T { + if err != nil { + panic(err) + } + return r +} diff --git a/x/staking/simulation/operations.go b/x/staking/simulation/operations.go deleted file mode 100644 index 83ca16fb43c6..000000000000 --- a/x/staking/simulation/operations.go +++ /dev/null @@ -1,873 +0,0 @@ -package simulation - -import ( - "bytes" - "fmt" - "math/rand" - - "cosmossdk.io/math" - "cosmossdk.io/x/staking/keeper" - "cosmossdk.io/x/staking/types" - - "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/codec" - "github.com/cosmos/cosmos-sdk/testutil" - sdk "github.com/cosmos/cosmos-sdk/types" - simtypes "github.com/cosmos/cosmos-sdk/types/simulation" - "github.com/cosmos/cosmos-sdk/x/simulation" -) - -// Simulation operation weights constants -const ( - DefaultWeightMsgCreateValidator int = 100 - DefaultWeightMsgEditValidator int = 5 - DefaultWeightMsgDelegate int = 100 - DefaultWeightMsgUndelegate int = 100 - DefaultWeightMsgBeginRedelegate int = 100 - DefaultWeightMsgCancelUnbondingDelegation int = 100 - DefaultWeightMsgRotateConsPubKey int = 100 - - OpWeightMsgCreateValidator = "op_weight_msg_create_validator" - OpWeightMsgEditValidator = "op_weight_msg_edit_validator" - OpWeightMsgDelegate = "op_weight_msg_delegate" - OpWeightMsgUndelegate = "op_weight_msg_undelegate" - OpWeightMsgBeginRedelegate = "op_weight_msg_begin_redelegate" - OpWeightMsgCancelUnbondingDelegation = "op_weight_msg_cancel_unbonding_delegation" - OpWeightMsgRotateConsPubKey = "op_weight_msg_rotate_cons_pubkey" -) - -// WeightedOperations returns all the operations from the module with their respective weights -func WeightedOperations( - appParams simtypes.AppParams, - cdc codec.JSONCodec, - txGen client.TxConfig, - ak types.AccountKeeper, - bk types.BankKeeper, - k *keeper.Keeper, -) simulation.WeightedOperations { - var ( - weightMsgCreateValidator int - weightMsgEditValidator int - weightMsgDelegate int - weightMsgUndelegate int - weightMsgBeginRedelegate int - weightMsgCancelUnbondingDelegation int - weightMsgRotateConsPubKey int - ) - - appParams.GetOrGenerate(OpWeightMsgCreateValidator, &weightMsgCreateValidator, nil, func(_ *rand.Rand) { - weightMsgCreateValidator = DefaultWeightMsgCreateValidator - }) - - appParams.GetOrGenerate(OpWeightMsgEditValidator, &weightMsgEditValidator, nil, func(_ *rand.Rand) { - weightMsgEditValidator = DefaultWeightMsgEditValidator - }) - - appParams.GetOrGenerate(OpWeightMsgDelegate, &weightMsgDelegate, nil, func(_ *rand.Rand) { - weightMsgDelegate = DefaultWeightMsgDelegate - }) - - appParams.GetOrGenerate(OpWeightMsgUndelegate, &weightMsgUndelegate, nil, func(_ *rand.Rand) { - weightMsgUndelegate = DefaultWeightMsgUndelegate - }) - - appParams.GetOrGenerate(OpWeightMsgBeginRedelegate, &weightMsgBeginRedelegate, nil, func(_ *rand.Rand) { - weightMsgBeginRedelegate = DefaultWeightMsgBeginRedelegate - }) - - appParams.GetOrGenerate(OpWeightMsgCancelUnbondingDelegation, &weightMsgCancelUnbondingDelegation, nil, func(_ *rand.Rand) { - weightMsgCancelUnbondingDelegation = DefaultWeightMsgCancelUnbondingDelegation - }) - - appParams.GetOrGenerate(OpWeightMsgRotateConsPubKey, &weightMsgRotateConsPubKey, nil, func(_ *rand.Rand) { - weightMsgRotateConsPubKey = DefaultWeightMsgRotateConsPubKey - }) - - return simulation.WeightedOperations{ - simulation.NewWeightedOperation( - weightMsgCreateValidator, - SimulateMsgCreateValidator(txGen, ak, bk, k), - ), - simulation.NewWeightedOperation( - weightMsgEditValidator, - SimulateMsgEditValidator(txGen, ak, bk, k), - ), - simulation.NewWeightedOperation( - weightMsgDelegate, - SimulateMsgDelegate(txGen, ak, bk, k), - ), - simulation.NewWeightedOperation( - weightMsgUndelegate, - SimulateMsgUndelegate(txGen, ak, bk, k), - ), - simulation.NewWeightedOperation( - weightMsgBeginRedelegate, - SimulateMsgBeginRedelegate(txGen, ak, bk, k), - ), - simulation.NewWeightedOperation( - weightMsgCancelUnbondingDelegation, - SimulateMsgCancelUnbondingDelegate(txGen, ak, bk, k), - ), - simulation.NewWeightedOperation( - weightMsgRotateConsPubKey, - SimulateMsgRotateConsPubKey(txGen, ak, bk, k), - ), - } -} - -// SimulateMsgCreateValidator generates a MsgCreateValidator with random values -func SimulateMsgCreateValidator( - txGen client.TxConfig, - ak types.AccountKeeper, - bk types.BankKeeper, - k *keeper.Keeper, -) simtypes.Operation { - return func( - r *rand.Rand, app simtypes.AppEntrypoint, ctx sdk.Context, accs []simtypes.Account, chainID string, - ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { - msgType := sdk.MsgTypeURL(&types.MsgCreateValidator{}) - - simAccount, _ := simtypes.RandomAcc(r, accs) - address := sdk.ValAddress(simAccount.Address) - - // ensure the validator doesn't exist already - _, err := k.GetValidator(ctx, address) - if err == nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "validator already exists"), nil, nil - } - - consPubKey := sdk.GetConsAddress(simAccount.ConsKey.PubKey()) - _, err = k.GetValidatorByConsAddr(ctx, consPubKey) - if err == nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "cons key already used"), nil, nil - } - - denom, err := k.BondDenom(ctx) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "bond denom not found"), nil, err - } - - balance := bk.GetBalance(ctx, simAccount.Address, denom).Amount - if !balance.IsPositive() { - return simtypes.NoOpMsg(types.ModuleName, msgType, "balance is negative"), nil, nil - } - - amount, err := simtypes.RandPositiveInt(r, balance) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "unable to generate positive amount"), nil, err - } - - selfDelegation := sdk.NewCoin(denom, amount) - - account := ak.GetAccount(ctx, simAccount.Address) - spendable := bk.SpendableCoins(ctx, account.GetAddress()) - - var fees sdk.Coins - - coins, hasNeg := spendable.SafeSub(selfDelegation) - if !hasNeg { - fees, err = simtypes.RandomFees(r, coins) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "unable to generate fees"), nil, err - } - } - - description := types.NewDescription( - simtypes.RandStringOfLength(r, 10), - simtypes.RandStringOfLength(r, 10), - simtypes.RandStringOfLength(r, 10), - simtypes.RandStringOfLength(r, 10), - simtypes.RandStringOfLength(r, 10), - ) - - maxCommission := math.LegacyNewDecWithPrec(int64(simtypes.RandIntBetween(r, 0, 100)), 2) - commission := types.NewCommissionRates( - simtypes.RandomDecAmount(r, maxCommission), - maxCommission, - simtypes.RandomDecAmount(r, maxCommission), - ) - - addr, err := k.ValidatorAddressCodec().BytesToString(address) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "unable to generate validator address"), nil, err - } - - msg, err := types.NewMsgCreateValidator(addr, simAccount.ConsKey.PubKey(), selfDelegation, description, commission, math.OneInt()) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(msg), "unable to create CreateValidator message"), nil, err - } - - // check if there's another key rotation for this same key in the same block - allRotations, err := k.GetBlockConsPubKeyRotationHistory(ctx) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "cannot get block cons key rotation history"), nil, err - } - for _, r := range allRotations { - if r.NewConsPubkey.Compare(msg.Pubkey) == 0 { - return simtypes.NoOpMsg(types.ModuleName, msgType, "cons key already used in this block"), nil, nil - } - } - - txCtx := simulation.OperationInput{ - R: r, - App: app, - TxGen: txGen, - Cdc: nil, - Msg: msg, - Context: ctx, - SimAccount: simAccount, - AccountKeeper: ak, - ModuleName: types.ModuleName, - } - - return simulation.GenAndDeliverTx(txCtx, fees) - } -} - -// SimulateMsgEditValidator generates a MsgEditValidator with random values -func SimulateMsgEditValidator( - txGen client.TxConfig, - ak types.AccountKeeper, - bk types.BankKeeper, - k *keeper.Keeper, -) simtypes.Operation { - return func( - r *rand.Rand, app simtypes.AppEntrypoint, ctx sdk.Context, accs []simtypes.Account, chainID string, - ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { - msgType := sdk.MsgTypeURL(&types.MsgEditValidator{}) - - vals, err := k.GetAllValidators(ctx) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "unable to get validators"), nil, err - } - - if len(vals) == 0 { - return simtypes.NoOpMsg(types.ModuleName, msgType, "number of validators equal zero"), nil, nil - } - - val, ok := testutil.RandSliceElem(r, vals) - if !ok { - return simtypes.NoOpMsg(types.ModuleName, msgType, "unable to pick a validator"), nil, nil - } - - address := val.GetOperator() - newCommissionRate := simtypes.RandomDecAmount(r, val.Commission.MaxRate) - - if err := val.Commission.ValidateNewRate(newCommissionRate, ctx.HeaderInfo().Time); err != nil { - // skip as the commission is invalid - return simtypes.NoOpMsg(types.ModuleName, msgType, "invalid commission rate"), nil, nil - } - - bz, err := k.ValidatorAddressCodec().StringToBytes(val.GetOperator()) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "error getting validator address bytes"), nil, err - } - - simAccount, found := simtypes.FindAccount(accs, sdk.AccAddress(bz)) - if !found { - return simtypes.NoOpMsg(types.ModuleName, msgType, "unable to find account"), nil, fmt.Errorf("validator %s not found", val.GetOperator()) - } - - account := ak.GetAccount(ctx, simAccount.Address) - spendable := bk.SpendableCoins(ctx, account.GetAddress()) - - description := types.NewDescription( - simtypes.RandStringOfLength(r, 10), - simtypes.RandStringOfLength(r, 10), - simtypes.RandStringOfLength(r, 10), - simtypes.RandStringOfLength(r, 10), - simtypes.RandStringOfLength(r, 10), - ) - - msg := types.NewMsgEditValidator(address, description, &newCommissionRate, nil) - - txCtx := simulation.OperationInput{ - R: r, - App: app, - TxGen: txGen, - Cdc: nil, - Msg: msg, - Context: ctx, - SimAccount: simAccount, - AccountKeeper: ak, - Bankkeeper: bk, - ModuleName: types.ModuleName, - CoinsSpentInMsg: spendable, - } - - return simulation.GenAndDeliverTxWithRandFees(txCtx) - } -} - -// SimulateMsgDelegate generates a MsgDelegate with random values -func SimulateMsgDelegate( - txGen client.TxConfig, - ak types.AccountKeeper, - bk types.BankKeeper, - k *keeper.Keeper, -) simtypes.Operation { - return func( - r *rand.Rand, app simtypes.AppEntrypoint, ctx sdk.Context, accs []simtypes.Account, chainID string, - ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { - msgType := sdk.MsgTypeURL(&types.MsgDelegate{}) - denom, err := k.BondDenom(ctx) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "bond denom not found"), nil, err - } - - vals, err := k.GetAllValidators(ctx) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "unable to get validators"), nil, err - } - - if len(vals) == 0 { - return simtypes.NoOpMsg(types.ModuleName, msgType, "number of validators equal zero"), nil, nil - } - - simAccount, _ := simtypes.RandomAcc(r, accs) - val, ok := testutil.RandSliceElem(r, vals) - if !ok { - return simtypes.NoOpMsg(types.ModuleName, msgType, "unable to pick a validator"), nil, nil - } - - if val.InvalidExRate() { - return simtypes.NoOpMsg(types.ModuleName, msgType, "validator's invalid echange rate"), nil, nil - } - - amount := bk.GetBalance(ctx, simAccount.Address, denom).Amount - if !amount.IsPositive() { - return simtypes.NoOpMsg(types.ModuleName, msgType, "balance is negative"), nil, nil - } - - amount, err = simtypes.RandPositiveInt(r, amount) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "unable to generate positive amount"), nil, err - } - - bondAmt := sdk.NewCoin(denom, amount) - - account := ak.GetAccount(ctx, simAccount.Address) - spendable := bk.SpendableCoins(ctx, account.GetAddress()) - - var fees sdk.Coins - - coins, hasNeg := spendable.SafeSub(bondAmt) - if !hasNeg { - fees, err = simtypes.RandomFees(r, coins) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "unable to generate fees"), nil, err - } - } - - accAddr, err := ak.AddressCodec().BytesToString(simAccount.Address) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "error getting account string address"), nil, err - } - msg := types.NewMsgDelegate(accAddr, val.GetOperator(), bondAmt) - - txCtx := simulation.OperationInput{ - R: r, - App: app, - TxGen: txGen, - Cdc: nil, - Msg: msg, - Context: ctx, - SimAccount: simAccount, - AccountKeeper: ak, - ModuleName: types.ModuleName, - } - - return simulation.GenAndDeliverTx(txCtx, fees) - } -} - -// SimulateMsgUndelegate generates a MsgUndelegate with random values -func SimulateMsgUndelegate( - txGen client.TxConfig, - ak types.AccountKeeper, - bk types.BankKeeper, - k *keeper.Keeper, -) simtypes.Operation { - return func( - r *rand.Rand, app simtypes.AppEntrypoint, ctx sdk.Context, accs []simtypes.Account, chainID string, - ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { - msgType := sdk.MsgTypeURL(&types.MsgUndelegate{}) - - vals, err := k.GetAllValidators(ctx) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "unable to get validators"), nil, err - } - - if len(vals) == 0 { - return simtypes.NoOpMsg(types.ModuleName, msgType, "number of validators equal zero"), nil, nil - } - - val, ok := testutil.RandSliceElem(r, vals) - if !ok { - return simtypes.NoOpMsg(types.ModuleName, msgType, "validator is not ok"), nil, nil - } - - valAddr, err := k.ValidatorAddressCodec().StringToBytes(val.GetOperator()) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "error getting validator address bytes"), nil, err - } - delegations, err := k.GetValidatorDelegations(ctx, valAddr) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "error getting validator delegations"), nil, nil - } - - if delegations == nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "keeper does have any delegation entries"), nil, nil - } - - // get random delegator from validator - delegation := delegations[r.Intn(len(delegations))] - delAddr := delegation.GetDelegatorAddr() - - delAddrBz, err := ak.AddressCodec().StringToBytes(delAddr) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "error getting delegator address bytes"), nil, err - } - - hasMaxUD, err := k.HasMaxUnbondingDelegationEntries(ctx, delAddrBz, valAddr) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "error getting max unbonding delegation entries"), nil, err - } - - if hasMaxUD { - return simtypes.NoOpMsg(types.ModuleName, msgType, "keeper does have a max unbonding delegation entries"), nil, nil - } - - totalBond := val.TokensFromShares(delegation.GetShares()).TruncateInt() - if !totalBond.IsPositive() { - return simtypes.NoOpMsg(types.ModuleName, msgType, "total bond is negative"), nil, nil - } - - unbondAmt, err := simtypes.RandPositiveInt(r, totalBond) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "invalid unbond amount"), nil, err - } - - if unbondAmt.IsZero() { - return simtypes.NoOpMsg(types.ModuleName, msgType, "unbond amount is zero"), nil, nil - } - - bondDenom, err := k.BondDenom(ctx) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "bond denom not found"), nil, err - } - - msg := types.NewMsgUndelegate( - delAddr, val.GetOperator(), sdk.NewCoin(bondDenom, unbondAmt), - ) - - if !bk.IsSendEnabledDenom(ctx, bondDenom) { - return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(msg), "bond denom send not enabled"), nil, nil - } - - // need to retrieve the simulation account associated with delegation to retrieve PrivKey - var simAccount simtypes.Account - - for _, simAcc := range accs { - if simAcc.Address.Equals(sdk.AccAddress(delAddrBz)) { - simAccount = simAcc - break - } - } - // if simaccount.PrivKey == nil, delegation address does not exist in accs. However, since smart contracts and module accounts can stake, we can ignore the error - if simAccount.PrivKey == nil { - return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(msg), "account private key is nil"), nil, nil - } - - account := ak.GetAccount(ctx, delAddrBz) - spendable := bk.SpendableCoins(ctx, account.GetAddress()) - - txCtx := simulation.OperationInput{ - R: r, - App: app, - TxGen: txGen, - Cdc: nil, - Msg: msg, - Context: ctx, - SimAccount: simAccount, - AccountKeeper: ak, - Bankkeeper: bk, - ModuleName: types.ModuleName, - CoinsSpentInMsg: spendable, - } - - return simulation.GenAndDeliverTxWithRandFees(txCtx) - } -} - -// SimulateMsgCancelUnbondingDelegate generates a MsgCancelUnbondingDelegate with random values -func SimulateMsgCancelUnbondingDelegate( - txGen client.TxConfig, - ak types.AccountKeeper, - bk types.BankKeeper, - k *keeper.Keeper, -) simtypes.Operation { - return func( - r *rand.Rand, app simtypes.AppEntrypoint, ctx sdk.Context, accs []simtypes.Account, chainID string, - ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { - msgType := sdk.MsgTypeURL(&types.MsgCancelUnbondingDelegation{}) - - vals, err := k.GetAllValidators(ctx) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "unable to get validators"), nil, err - } - - if len(vals) == 0 { - return simtypes.NoOpMsg(types.ModuleName, msgType, "number of validators equal zero"), nil, nil - } - - simAccount, _ := simtypes.RandomAcc(r, accs) - val, ok := testutil.RandSliceElem(r, vals) - if !ok { - return simtypes.NoOpMsg(types.ModuleName, msgType, "validator is not ok"), nil, nil - } - - if val.IsJailed() || val.InvalidExRate() { - return simtypes.NoOpMsg(types.ModuleName, msgType, "validator is jailed"), nil, nil - } - - valAddr, err := k.ValidatorAddressCodec().StringToBytes(val.GetOperator()) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "error getting validator address bytes"), nil, err - } - unbondingDelegation, err := k.GetUnbondingDelegation(ctx, simAccount.Address, valAddr) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "account does have any unbonding delegation"), nil, nil - } - - // This is a temporary fix to make staking simulation pass. We should fetch - // the first unbondingDelegationEntry that matches the creationHeight, because - // currently the staking msgServer chooses the first unbondingDelegationEntry - // with the matching creationHeight. - // - // ref: https://github.com/cosmos/cosmos-sdk/issues/12932 - creationHeight := unbondingDelegation.Entries[r.Intn(len(unbondingDelegation.Entries))].CreationHeight - - var unbondingDelegationEntry types.UnbondingDelegationEntry - - for _, entry := range unbondingDelegation.Entries { - if entry.CreationHeight == creationHeight { - unbondingDelegationEntry = entry - break - } - } - - if unbondingDelegationEntry.CompletionTime.Before(ctx.HeaderInfo().Time) { - return simtypes.NoOpMsg(types.ModuleName, msgType, "unbonding delegation is already processed"), nil, nil - } - - if !unbondingDelegationEntry.Balance.IsPositive() { - return simtypes.NoOpMsg(types.ModuleName, msgType, "delegator receiving balance is negative"), nil, nil - } - - cancelBondAmt := simtypes.RandomAmount(r, unbondingDelegationEntry.Balance) - - if cancelBondAmt.IsZero() { - return simtypes.NoOpMsg(types.ModuleName, msgType, "cancelBondAmt amount is zero"), nil, nil - } - - bondDenom, err := k.BondDenom(ctx) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "bond denom not found"), nil, err - } - - accAddr, err := ak.AddressCodec().BytesToString(simAccount.Address) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "error getting account string address"), nil, err - } - msg := types.NewMsgCancelUnbondingDelegation( - accAddr, val.GetOperator(), unbondingDelegationEntry.CreationHeight, sdk.NewCoin(bondDenom, cancelBondAmt), - ) - - spendable := bk.SpendableCoins(ctx, simAccount.Address) - - txCtx := simulation.OperationInput{ - R: r, - App: app, - TxGen: txGen, - Cdc: nil, - Msg: msg, - Context: ctx, - SimAccount: simAccount, - AccountKeeper: ak, - Bankkeeper: bk, - ModuleName: types.ModuleName, - CoinsSpentInMsg: spendable, - } - - return simulation.GenAndDeliverTxWithRandFees(txCtx) - } -} - -// SimulateMsgBeginRedelegate generates a MsgBeginRedelegate with random values -func SimulateMsgBeginRedelegate( - txGen client.TxConfig, - ak types.AccountKeeper, - bk types.BankKeeper, - k *keeper.Keeper, -) simtypes.Operation { - return func( - r *rand.Rand, app simtypes.AppEntrypoint, ctx sdk.Context, accs []simtypes.Account, chainID string, - ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { - msgType := sdk.MsgTypeURL(&types.MsgBeginRedelegate{}) - - allVals, err := k.GetAllValidators(ctx) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "unable to get validators"), nil, err - } - - if len(allVals) == 0 { - return simtypes.NoOpMsg(types.ModuleName, msgType, "number of validators equal zero"), nil, nil - } - - srcVal, ok := testutil.RandSliceElem(r, allVals) - if !ok { - return simtypes.NoOpMsg(types.ModuleName, msgType, "unable to pick validator"), nil, nil - } - - srcAddr, err := k.ValidatorAddressCodec().StringToBytes(srcVal.GetOperator()) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "error getting validator address bytes"), nil, err - } - delegations, err := k.GetValidatorDelegations(ctx, srcAddr) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "error getting validator delegations"), nil, nil - } - - if delegations == nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "keeper does have any delegation entries"), nil, nil - } - - // get random delegator from src validator - delegation := delegations[r.Intn(len(delegations))] - delAddr := delegation.GetDelegatorAddr() - - delAddrBz, err := ak.AddressCodec().StringToBytes(delAddr) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "error getting delegator address bytes"), nil, err - } - - hasRecRedel, err := k.HasReceivingRedelegation(ctx, delAddrBz, srcAddr) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "error getting receiving redelegation"), nil, err - } - - if hasRecRedel { - return simtypes.NoOpMsg(types.ModuleName, msgType, "receveing redelegation is not allowed"), nil, nil // skip - } - - // get random destination validator - destVal, ok := testutil.RandSliceElem(r, allVals) - if !ok { - return simtypes.NoOpMsg(types.ModuleName, msgType, "unable to pick validator"), nil, nil - } - - destAddr, err := k.ValidatorAddressCodec().StringToBytes(destVal.GetOperator()) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "error getting validator address bytes"), nil, err - } - hasMaxRedel, err := k.HasMaxRedelegationEntries(ctx, delAddrBz, srcAddr, destAddr) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "error getting max redelegation entries"), nil, err - } - - if bytes.Equal(srcAddr, destAddr) || destVal.InvalidExRate() || hasMaxRedel { - return simtypes.NoOpMsg(types.ModuleName, msgType, "checks failed"), nil, nil - } - - totalBond := srcVal.TokensFromShares(delegation.GetShares()).TruncateInt() - if !totalBond.IsPositive() { - return simtypes.NoOpMsg(types.ModuleName, msgType, "total bond is negative"), nil, nil - } - - redAmt, err := simtypes.RandPositiveInt(r, totalBond) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "unable to generate positive amount"), nil, err - } - - if redAmt.IsZero() { - return simtypes.NoOpMsg(types.ModuleName, msgType, "amount is zero"), nil, nil - } - - // check if the shares truncate to zero - shares, err := srcVal.SharesFromTokens(redAmt) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "invalid shares"), nil, err - } - - if srcVal.TokensFromShares(shares).TruncateInt().IsZero() { - return simtypes.NoOpMsg(types.ModuleName, msgType, "shares truncate to zero"), nil, nil // skip - } - - // need to retrieve the simulation account associated with delegation to retrieve PrivKey - var simAccount simtypes.Account - - for _, simAcc := range accs { - if simAcc.Address.Equals(sdk.AccAddress(delAddrBz)) { - simAccount = simAcc - break - } - } - - // if simaccount.PrivKey == nil, delegation address does not exist in accs. However, since smart contracts and module accounts can stake, we can ignore the error - if simAccount.PrivKey == nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "account private key is nil"), nil, nil - } - - account := ak.GetAccount(ctx, delAddrBz) - spendable := bk.SpendableCoins(ctx, account.GetAddress()) - - bondDenom, err := k.BondDenom(ctx) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "bond denom not found"), nil, err - } - - if !bk.IsSendEnabledDenom(ctx, bondDenom) { - return simtypes.NoOpMsg(types.ModuleName, msgType, "bond denom send not enabled"), nil, nil - } - - msg := types.NewMsgBeginRedelegate( - delAddr, srcVal.GetOperator(), destVal.GetOperator(), - sdk.NewCoin(bondDenom, redAmt), - ) - - txCtx := simulation.OperationInput{ - R: r, - App: app, - TxGen: txGen, - Cdc: nil, - Msg: msg, - Context: ctx, - SimAccount: simAccount, - AccountKeeper: ak, - Bankkeeper: bk, - ModuleName: types.ModuleName, - CoinsSpentInMsg: spendable, - } - - return simulation.GenAndDeliverTxWithRandFees(txCtx) - } -} - -func SimulateMsgRotateConsPubKey(txGen client.TxConfig, ak types.AccountKeeper, bk types.BankKeeper, k *keeper.Keeper) simtypes.Operation { - return func( - r *rand.Rand, app simtypes.AppEntrypoint, ctx sdk.Context, accs []simtypes.Account, chainID string, - ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { - msgType := sdk.MsgTypeURL(&types.MsgRotateConsPubKey{}) - - vals, err := k.GetAllValidators(ctx) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "unable to get validators"), nil, err - } - - if len(vals) == 0 { - return simtypes.NoOpMsg(types.ModuleName, msgType, "number of validators equal zero"), nil, nil - } - - val, ok := testutil.RandSliceElem(r, vals) - if !ok { - return simtypes.NoOpMsg(types.ModuleName, msgType, "unable to pick a validator"), nil, nil - } - - if val.Status != types.Bonded || val.ConsensusPower(sdk.DefaultPowerReduction) == 0 { - return simtypes.NoOpMsg(types.ModuleName, msgType, "validator not bonded."), nil, nil - } - - valAddr := val.GetOperator() - valBytes, err := k.ValidatorAddressCodec().StringToBytes(valAddr) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "error getting validator address bytes"), nil, err - } - - simAccount, found := simtypes.FindAccount(accs, sdk.AccAddress(valBytes)) - if !found { - return simtypes.NoOpMsg(types.ModuleName, msgType, "unable to find account"), nil, fmt.Errorf("validator %s not found", val.GetOperator()) - } - - cons, err := val.GetConsAddr() - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "cannot get conskey"), nil, err - } - consAddress, err := k.ConsensusAddressCodec().BytesToString(cons) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "error getting consensus address"), nil, err - } - - acc, _ := simtypes.RandomAcc(r, accs) - accAddress, err := k.ConsensusAddressCodec().BytesToString(acc.ConsKey.PubKey().Address()) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "error getting consensus address"), nil, err - } - if consAddress == accAddress { - return simtypes.NoOpMsg(types.ModuleName, msgType, "new pubkey and current pubkey should be different"), nil, nil - } - - account := ak.GetAccount(ctx, simAccount.Address) - if account == nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "unable to find account"), nil, nil - } - - spendable := bk.SpendableCoins(ctx, account.GetAddress()) - params, err := k.Params.Get(ctx) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "cannot get params"), nil, err - } - - if !spendable.IsAllGTE(sdk.NewCoins(params.KeyRotationFee)) { - return simtypes.NoOpMsg(types.ModuleName, msgType, "not enough balance to pay fee"), nil, nil - } - - if err := k.ExceedsMaxRotations(ctx, valBytes); err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "rotations limit reached within unbonding period"), nil, nil - } - - _, err = k.GetValidatorByConsAddr(ctx, cons) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "cannot get validator"), nil, err - } - - // check whether the new cons key associated with another validator - newConsAddr := sdk.ConsAddress(acc.ConsKey.PubKey().Address()) - _, err = k.GetValidatorByConsAddr(ctx, newConsAddr) - if err == nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "cons key already used"), nil, nil - } - - msg, err := types.NewMsgRotateConsPubKey(valAddr, acc.ConsKey.PubKey()) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "unable to build msg"), nil, err - } - - // check if there's another key rotation for this same key in the same block - allRotations, err := k.GetBlockConsPubKeyRotationHistory(ctx) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, msgType, "cannot get block cons key rotation history"), nil, err - } - for _, r := range allRotations { - if r.NewConsPubkey.Compare(msg.NewPubkey) == 0 { - return simtypes.NoOpMsg(types.ModuleName, msgType, "cons key already used in this block"), nil, nil - } - } - - txCtx := simulation.OperationInput{ - R: r, - App: app, - TxGen: txGen, - Cdc: nil, - Msg: msg, - Context: ctx, - SimAccount: simAccount, - AccountKeeper: ak, - Bankkeeper: bk, - ModuleName: types.ModuleName, - CoinsSpentInMsg: spendable, - } - - return simulation.GenAndDeliverTxWithRandFees(txCtx) - } -} diff --git a/x/staking/simulation/proposals.go b/x/staking/simulation/proposals.go deleted file mode 100644 index 36afe6db90d3..000000000000 --- a/x/staking/simulation/proposals.go +++ /dev/null @@ -1,56 +0,0 @@ -package simulation - -import ( - "context" - "math/rand" - "time" - - coreaddress "cosmossdk.io/core/address" - "cosmossdk.io/x/staking/types" - - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/types/address" - simtypes "github.com/cosmos/cosmos-sdk/types/simulation" - "github.com/cosmos/cosmos-sdk/x/simulation" -) - -// Simulation operation weights constants -const ( - DefaultWeightMsgUpdateParams int = 100 - - OpWeightMsgUpdateParams = "op_weight_msg_update_params" -) - -// ProposalMsgs defines the module weighted proposals' contents -func ProposalMsgs() []simtypes.WeightedProposalMsg { - return []simtypes.WeightedProposalMsg{ - simulation.NewWeightedProposalMsgX( - OpWeightMsgUpdateParams, - DefaultWeightMsgUpdateParams, - SimulateMsgUpdateParams, - ), - } -} - -// SimulateMsgUpdateParams returns a random MsgUpdateParams -func SimulateMsgUpdateParams(_ context.Context, r *rand.Rand, _ []simtypes.Account, addressCodec coreaddress.Codec) (sdk.Msg, error) { - // use the default gov module account address as authority - var authority sdk.AccAddress = address.Module("gov") - - params := types.DefaultParams() - params.HistoricalEntries = uint32(simtypes.RandIntBetween(r, 0, 1000)) - params.MaxEntries = uint32(simtypes.RandIntBetween(r, 1, 1000)) - params.MaxValidators = uint32(simtypes.RandIntBetween(r, 1, 1000)) - params.UnbondingTime = time.Duration(simtypes.RandTimestamp(r).UnixNano()) - // changes to MinCommissionRate or BondDenom create issues for in flight messages or state operations - - addr, err := addressCodec.BytesToString(authority) - if err != nil { - return nil, err - } - - return &types.MsgUpdateParams{ - Authority: addr, - Params: params, - }, nil -} diff --git a/x/staking/simulation/proposals_test.go b/x/staking/simulation/proposals_test.go deleted file mode 100644 index 4373ae15b290..000000000000 --- a/x/staking/simulation/proposals_test.go +++ /dev/null @@ -1,49 +0,0 @@ -package simulation_test - -import ( - "context" - "math/rand" - "testing" - - "gotest.tools/v3/assert" - - "cosmossdk.io/x/staking/simulation" - "cosmossdk.io/x/staking/types" - - codectestutil "github.com/cosmos/cosmos-sdk/codec/testutil" - "github.com/cosmos/cosmos-sdk/types/address" - simtypes "github.com/cosmos/cosmos-sdk/types/simulation" -) - -func TestProposalMsgs(t *testing.T) { - // initialize parameters - s := rand.NewSource(1) - r := rand.New(s) - - accounts := simtypes.RandomAccounts(r, 3) - addressCodec := codectestutil.CodecOptions{}.GetAddressCodec() - // execute ProposalMsgs function - weightedProposalMsgs := simulation.ProposalMsgs() - assert.Assert(t, len(weightedProposalMsgs) == 1) - - w0 := weightedProposalMsgs[0] - - // tests w0 interface: - assert.Equal(t, simulation.OpWeightMsgUpdateParams, w0.AppParamsKey()) - assert.Equal(t, simulation.DefaultWeightMsgUpdateParams, w0.DefaultWeight()) - - msg, err := w0.MsgSimulatorFn()(context.Background(), r, accounts, addressCodec) - assert.NilError(t, err) - msgUpdateParams, ok := msg.(*types.MsgUpdateParams) - assert.Assert(t, ok) - - addr, err := addressCodec.BytesToString(address.Module("gov")) - assert.NilError(t, err) - - assert.Equal(t, addr, msgUpdateParams.Authority) - assert.Equal(t, "stake", msgUpdateParams.Params.BondDenom) - assert.Equal(t, uint32(905), msgUpdateParams.Params.MaxEntries) - assert.Equal(t, uint32(540), msgUpdateParams.Params.HistoricalEntries) - assert.Equal(t, uint32(151), msgUpdateParams.Params.MaxValidators) - assert.Equal(t, "2417694h42m25s", msgUpdateParams.Params.UnbondingTime.String()) -} diff --git a/x/staking/simulation/rand_util.go b/x/staking/simulation/rand_util.go new file mode 100644 index 000000000000..c847a66f788f --- /dev/null +++ b/x/staking/simulation/rand_util.go @@ -0,0 +1,36 @@ +package simulation + +import ( + "fmt" + "math/rand" + "net/url" + + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" +) + +// RandURIOfHostLength returns a random valid uri with hostname length n. If n = 0, returns an empty string. +func RandURIOfHostLength(r *rand.Rand, n int) string { + if n == 0 { + return "" + } + tld := ".com" + hostLength := n - len(tld) + uri := &url.URL{ + Scheme: "https", + Host: fmt.Sprintf("%s%s", simtypes.RandStringOfLength(r, hostLength), tld), + } + + return uri.String() +} + +// RandSocialHandleURIs returns a string array of length num with uris. +func RandSocialHandleURIs(r *rand.Rand, num, uriHostLength int) []string { + if num == 0 { + return []string{} + } + var socialHandles []string + for i := 0; i < num; i++ { + socialHandles = append(socialHandles, RandURIOfHostLength(r, uriHostLength)) + } + return socialHandles +} diff --git a/x/staking/simulation/rand_util_test.go b/x/staking/simulation/rand_util_test.go new file mode 100644 index 000000000000..fb619e784eee --- /dev/null +++ b/x/staking/simulation/rand_util_test.go @@ -0,0 +1,60 @@ +package simulation_test + +import ( + "math/rand" + "net/url" + "testing" + "time" + + "github.com/stretchr/testify/require" + + "cosmossdk.io/x/staking/simulation" +) + +func TestRandURIOfHostLength(t *testing.T) { + t.Parallel() + r := rand.New(rand.NewSource(time.Now().Unix())) + tests := []struct { + name string + n int + want int + }{ + {"0-size", 0, 0}, + {"10-size", 10, 10}, + {"1_000_000-size", 1_000_000, 1_000_000}, + } + for _, tt := range tests { + tc := tt + t.Run(tc.name, func(t *testing.T) { + got := 0 + uri := simulation.RandURIOfHostLength(r, tc.n) + if uri != "" { + parsedUri, err := url.Parse(uri) + require.NoError(t, err) + got = len(parsedUri.Host) + } + require.Equal(t, tc.want, got) + }) + } +} + +func TestRandSocialHandleURIs(t *testing.T) { + t.Parallel() + r := rand.New(rand.NewSource(time.Now().Unix())) + tests := []struct { + name string + n int + want int + }{ + {"0-handles", 0, 0}, + {"10-handles", 10, 10}, + {"100-handles", 100, 100}, + } + for _, tt := range tests { + tc := tt + t.Run(tc.name, func(t *testing.T) { + uris := simulation.RandSocialHandleURIs(r, tc.n, 10) + require.Equal(t, tc.want, len(uris)) + }) + } +} diff --git a/x/staking/types/authz_test.go b/x/staking/types/authz_test.go index 1a8a66420dc0..c4ab9dc7bbd8 100644 --- a/x/staking/types/authz_test.go +++ b/x/staking/types/authz_test.go @@ -408,7 +408,6 @@ func TestAuthzAuthorizations(t *testing.T) { } for _, tc := range testCases { - tc := tc t.Run(tc.msg, func(t *testing.T) { delAuth, err := stakingtypes.NewStakeAuthorization(tc.allowed, tc.denied, tc.msgType, tc.limit, valAddressCodec) require.NoError(t, err) diff --git a/x/staking/types/msg.go b/x/staking/types/msg.go index b68818275ddf..879d3c821540 100644 --- a/x/staking/types/msg.go +++ b/x/staking/types/msg.go @@ -64,7 +64,7 @@ func (msg MsgCreateValidator) Validate(ac address.Codec) error { return errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "invalid delegation amount") } - if msg.Description == (Description{}) { + if msg.Description.IsEmpty() { return errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "empty description") } diff --git a/x/staking/types/query.pb.go b/x/staking/types/query.pb.go index e78d8321bf06..4afae2c6fdd8 100644 --- a/x/staking/types/query.pb.go +++ b/x/staking/types/query.pb.go @@ -1492,96 +1492,96 @@ var fileDescriptor_f270127f442bbcd8 = []byte{ // 1467 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x59, 0xdd, 0x6b, 0x1c, 0x55, 0x14, 0xcf, 0xdd, 0xc4, 0x60, 0x4e, 0x69, 0x49, 0xef, 0x6e, 0xe3, 0x76, 0x9a, 0x6e, 0xb6, 0x43, - 0xad, 0x69, 0x6a, 0x66, 0xda, 0x54, 0xdb, 0x58, 0xa1, 0xed, 0xc6, 0xa2, 0xad, 0x2d, 0x35, 0x5d, - 0x31, 0x8a, 0x1f, 0x84, 0x49, 0x76, 0x3a, 0x19, 0x9a, 0xcc, 0x6c, 0xe7, 0x4e, 0x42, 0x4b, 0x29, - 0x82, 0x0f, 0x52, 0x5f, 0x44, 0xf0, 0x5d, 0xfa, 0x28, 0xa2, 0x20, 0x98, 0x0a, 0x22, 0xf6, 0x51, - 0xfa, 0x20, 0x52, 0x2a, 0x15, 0xf5, 0xa1, 0x4a, 0x23, 0xe8, 0x8b, 0xff, 0x81, 0x88, 0xcc, 0xcc, - 0x99, 0xaf, 0xcc, 0xe7, 0x6e, 0x76, 0x21, 0x7d, 0x09, 0xd9, 0x3b, 0xf7, 0x9c, 0xf3, 0xfb, 0xfd, - 0xce, 0x39, 0x77, 0xce, 0xdd, 0x05, 0x7e, 0x5e, 0x67, 0x4b, 0x3a, 0x13, 0x99, 0x29, 0x5d, 0x52, - 0x35, 0x45, 0x5c, 0x39, 0x34, 0x27, 0x9b, 0xd2, 0x21, 0xf1, 0xf2, 0xb2, 0x6c, 0x5c, 0x15, 0x9a, - 0x86, 0x6e, 0xea, 0x74, 0xc8, 0xd9, 0x23, 0xe0, 0x1e, 0x01, 0xf7, 0x70, 0x63, 0x68, 0x3b, 0x27, - 0x31, 0xd9, 0x31, 0xf0, 0xcc, 0x9b, 0x92, 0xa2, 0x6a, 0x92, 0xa9, 0xea, 0x9a, 0xe3, 0x83, 0x2b, - 0x29, 0xba, 0xa2, 0xdb, 0xff, 0x8a, 0xd6, 0x7f, 0xb8, 0x3a, 0xac, 0xe8, 0xba, 0xb2, 0x28, 0x8b, - 0x52, 0x53, 0x15, 0x25, 0x4d, 0xd3, 0x4d, 0xdb, 0x84, 0xe1, 0xd3, 0xbd, 0x09, 0xd8, 0x5c, 0x1c, - 0xce, 0xae, 0x9d, 0xce, 0xae, 0x59, 0xc7, 0x39, 0x42, 0x75, 0x1e, 0xed, 0x42, 0x07, 0x2e, 0xb6, - 0x20, 0x2b, 0x6e, 0xbb, 0xb4, 0xa4, 0x6a, 0xba, 0x68, 0xff, 0x75, 0x96, 0xf8, 0x2b, 0x30, 0x74, - 0xc1, 0xda, 0x31, 0x23, 0x2d, 0xaa, 0x0d, 0xc9, 0xd4, 0x0d, 0x56, 0x97, 0x2f, 0x2f, 0xcb, 0xcc, - 0xa4, 0x43, 0xd0, 0xcf, 0x4c, 0xc9, 0x5c, 0x66, 0x65, 0x52, 0x25, 0xa3, 0x03, 0x75, 0xfc, 0x44, - 0x5f, 0x04, 0xf0, 0xa9, 0x96, 0x0b, 0x55, 0x32, 0xba, 0x65, 0x62, 0x9f, 0x80, 0x20, 0x2c, 0x5d, - 0x04, 0x27, 0x24, 0x42, 0x17, 0xa6, 0x25, 0x45, 0x46, 0x9f, 0xf5, 0x80, 0x25, 0xbf, 0x00, 0x5b, - 0xbd, 0xa0, 0x67, 0xb4, 0x8b, 0x3a, 0xad, 0xc1, 0xf6, 0x79, 0x5d, 0x63, 0xb2, 0xc6, 0x96, 0xd9, - 0xac, 0xd4, 0x68, 0x18, 0x32, 0xc3, 0xd8, 0x53, 0xa5, 0xdf, 0x56, 0xc7, 0x07, 0xaf, 0xb8, 0x2a, - 0x54, 0x57, 0x0e, 0x0a, 0x13, 0xc2, 0xc1, 0xfa, 0xa0, 0xb7, 0xbd, 0xe6, 0xec, 0x3e, 0x56, 0xba, - 0x17, 0xb3, 0x8f, 0xff, 0xa0, 0x00, 0x4f, 0x44, 0x48, 0xb2, 0xa6, 0x65, 0x4c, 0xcf, 0x01, 0xac, - 0x78, 0xab, 0x65, 0x52, 0xed, 0x1d, 0xdd, 0x32, 0xb1, 0x47, 0x88, 0xcf, 0xbe, 0xe0, 0xd9, 0x4f, - 0x0d, 0xdc, 0x79, 0x30, 0xd2, 0xf3, 0xe9, 0x5f, 0x5f, 0x8e, 0x91, 0x7a, 0xc0, 0x9e, 0xbe, 0x0e, - 0xdb, 0xbc, 0x4f, 0xb3, 0xaa, 0x76, 0x51, 0x2f, 0x17, 0x6c, 0x8f, 0x4f, 0x66, 0x7a, 0xb4, 0x14, - 0x08, 0x7a, 0xdd, 0xba, 0x12, 0xd2, 0xe6, 0xa5, 0x90, 0xe8, 0xbd, 0xb6, 0xe8, 0x4f, 0x65, 0x8a, - 0xee, 0x70, 0x0c, 0xa9, 0x2e, 0xc1, 0x8e, 0xb0, 0x14, 0x6e, 0xba, 0x4f, 0x07, 0xa1, 0x5b, 0xea, - 0xa3, 0xf4, 0x7b, 0xee, 0xad, 0x8e, 0xef, 0xc6, 0x40, 0x9e, 0x11, 0xea, 0xfd, 0xaa, 0x69, 0xa8, - 0x9a, 0x12, 0xc0, 0x6a, 0xad, 0xf3, 0x8d, 0xf5, 0x25, 0xe5, 0x89, 0xfd, 0x32, 0x0c, 0x78, 0x5b, - 0x6d, 0xf7, 0xad, 0x6a, 0xed, 0x9b, 0xf3, 0xab, 0x04, 0xaa, 0xe1, 0x30, 0xa7, 0xe4, 0x45, 0x59, - 0x71, 0xba, 0xa9, 0xe3, 0xa4, 0x3a, 0x56, 0xf5, 0xff, 0x10, 0xd8, 0x93, 0x02, 0x1b, 0x85, 0x7a, - 0x17, 0x4a, 0x0d, 0x6f, 0x79, 0xd6, 0xc0, 0x65, 0xb7, 0x3e, 0xc7, 0x92, 0x34, 0xf3, 0x5d, 0xb9, - 0x9e, 0xa6, 0xaa, 0x96, 0x78, 0x9f, 0xfd, 0x3e, 0x52, 0x8c, 0x3e, 0x63, 0x8e, 0xa6, 0xc5, 0x46, - 0xf4, 0xc9, 0xba, 0x7a, 0x2b, 0xb4, 0x5f, 0x6f, 0xdf, 0x11, 0xd8, 0x1f, 0xe6, 0xfb, 0x9a, 0x36, - 0xa7, 0x6b, 0x0d, 0x55, 0x53, 0x1e, 0x89, 0x7c, 0x3d, 0x20, 0x30, 0x96, 0x07, 0x3f, 0x26, 0x4e, - 0x81, 0xe2, 0xb2, 0xfb, 0x3c, 0x92, 0xb7, 0x03, 0x49, 0x79, 0x8b, 0x71, 0x19, 0xac, 0x7a, 0xea, - 0xb9, 0xec, 0x42, 0x82, 0xbe, 0x20, 0xd8, 0xae, 0xc1, 0x02, 0x71, 0xb2, 0x71, 0x02, 0xb6, 0x61, - 0x6d, 0x84, 0xb3, 0x51, 0xbe, 0xb7, 0x3a, 0x5e, 0xc2, 0x50, 0xeb, 0x92, 0xe0, 0xed, 0xb7, 0x93, - 0x10, 0x4d, 0x67, 0xa1, 0xbd, 0x74, 0x1e, 0x7b, 0xfc, 0xc6, 0xcd, 0x91, 0x9e, 0xbf, 0x6f, 0x8e, - 0xf4, 0xf0, 0x2b, 0x78, 0x96, 0x47, 0xeb, 0x99, 0xbe, 0x05, 0xc5, 0x98, 0xae, 0xc1, 0x83, 0xa6, - 0x85, 0xa6, 0xa9, 0xd3, 0x68, 0x4b, 0xf0, 0x5f, 0x13, 0x18, 0xb1, 0x03, 0xc7, 0x24, 0x6b, 0x53, - 0x0b, 0x66, 0xe0, 0x39, 0x19, 0x8b, 0x1b, 0x95, 0x3b, 0x0f, 0xfd, 0x4e, 0x8d, 0xa1, 0x58, 0xed, - 0x56, 0x2a, 0x7a, 0xe1, 0x6f, 0xb9, 0x87, 0xf3, 0x29, 0x97, 0x5e, 0x4c, 0xb3, 0x6f, 0x58, 0xad, - 0x0e, 0xf5, 0x78, 0x40, 0xab, 0x9f, 0xdd, 0xd3, 0x39, 0x1e, 0x37, 0xaa, 0xb5, 0xd0, 0xb1, 0xd3, - 0x39, 0x20, 0x5d, 0x77, 0x8f, 0xe1, 0xdb, 0xee, 0x31, 0xec, 0x11, 0x4b, 0x3b, 0x86, 0x37, 0x61, - 0x66, 0xbc, 0x73, 0x38, 0x83, 0xc0, 0x23, 0x7b, 0x0e, 0xdf, 0x2e, 0xc0, 0x4e, 0x9b, 0x60, 0x5d, - 0x6e, 0x74, 0x25, 0x23, 0x94, 0x19, 0xf3, 0xb3, 0xb1, 0xa7, 0x4b, 0xb2, 0x93, 0x41, 0x66, 0xcc, - 0xcf, 0xac, 0x7b, 0xaf, 0xd2, 0x06, 0x33, 0xd7, 0xfb, 0xe9, 0xcd, 0xf2, 0xd3, 0x60, 0xe6, 0x4c, - 0xca, 0xfb, 0xb9, 0xaf, 0x03, 0x15, 0x72, 0x9f, 0x00, 0x17, 0x27, 0x20, 0x56, 0x84, 0x06, 0x43, - 0x86, 0x9c, 0xd2, 0xb6, 0x4f, 0x27, 0x15, 0x45, 0xd0, 0x5d, 0x5c, 0xe3, 0xee, 0x30, 0xe4, 0xae, - 0xb6, 0xee, 0xaa, 0xfb, 0xe2, 0xf1, 0x2a, 0x3f, 0x7a, 0x57, 0xdb, 0x84, 0x0d, 0xfb, 0x4d, 0xe4, - 0x15, 0xd0, 0xf5, 0xdb, 0x57, 0xc7, 0x24, 0xbf, 0x45, 0xa0, 0x92, 0x80, 0x7d, 0x53, 0xbf, 0xea, - 0x97, 0x12, 0x2b, 0xa5, 0x2b, 0x57, 0xb0, 0x49, 0x6c, 0xb8, 0xd3, 0x2a, 0x33, 0x75, 0x43, 0x9d, - 0x97, 0x16, 0xad, 0xbb, 0x6a, 0xe0, 0xfb, 0x83, 0x05, 0x59, 0x55, 0x16, 0x4c, 0x3b, 0x4c, 0x6f, - 0x1d, 0x3f, 0x1d, 0x2b, 0x94, 0x09, 0x2f, 0xc1, 0xae, 0x58, 0x4b, 0x04, 0x79, 0x1c, 0xfa, 0x16, - 0x54, 0x66, 0x22, 0xbe, 0x7d, 0x49, 0xf8, 0xc2, 0xd6, 0x53, 0x85, 0x32, 0xa9, 0xdb, 0x76, 0x76, - 0x08, 0x0a, 0x83, 0x76, 0x88, 0x69, 0x5d, 0x5f, 0x44, 0x48, 0xfc, 0x34, 0x6c, 0x0f, 0xac, 0x61, - 0xb0, 0xe7, 0xa1, 0xaf, 0xa9, 0xeb, 0x8b, 0x18, 0x6c, 0x38, 0x29, 0x98, 0x65, 0x13, 0xd4, 0xc1, - 0x36, 0xe2, 0x4b, 0x40, 0x1d, 0x8f, 0x92, 0x21, 0x2d, 0xb9, 0xed, 0xc8, 0xbf, 0x01, 0xc5, 0xd0, - 0x2a, 0x46, 0xaa, 0x41, 0x7f, 0xd3, 0x5e, 0xc1, 0x58, 0x95, 0xc4, 0x58, 0xf6, 0xae, 0xd0, 0x60, - 0xe5, 0x18, 0x4e, 0x7c, 0x35, 0x04, 0x8f, 0xd9, 0xae, 0xe9, 0x27, 0x04, 0xc0, 0xef, 0x28, 0x2a, - 0x24, 0xf9, 0x8a, 0xff, 0x76, 0x87, 0x13, 0x73, 0xef, 0xc7, 0xf9, 0x57, 0xbc, 0x61, 0x01, 0x79, - 0xef, 0xa7, 0x3f, 0x3f, 0x2e, 0xec, 0xa5, 0xbc, 0x98, 0xf0, 0x3d, 0x55, 0xa0, 0x1b, 0x3f, 0x27, - 0x30, 0xe0, 0xf9, 0xa1, 0xe3, 0xf9, 0xe2, 0xb9, 0xf0, 0x84, 0xbc, 0xdb, 0x11, 0xdd, 0x49, 0x1f, - 0xdd, 0xb3, 0xf4, 0x70, 0x36, 0x3a, 0xf1, 0x5a, 0xb8, 0xf9, 0xae, 0xd3, 0x5f, 0x09, 0x94, 0xe2, - 0xee, 0xe4, 0x74, 0x32, 0x1f, 0x94, 0xe8, 0x18, 0xc5, 0x3d, 0xd7, 0x86, 0x25, 0xf2, 0x39, 0xe7, - 0xf3, 0xa9, 0xd1, 0x13, 0x6d, 0xf0, 0x11, 0x03, 0xef, 0x40, 0xfa, 0x1f, 0x81, 0xdd, 0xa9, 0xf7, - 0x57, 0x5a, 0xcb, 0x07, 0x35, 0x65, 0x68, 0xe4, 0xa6, 0x36, 0xe2, 0x02, 0x69, 0xcf, 0xf8, 0xb4, - 0xcf, 0xd2, 0x33, 0xed, 0xd0, 0xf6, 0xa7, 0xbe, 0xa0, 0x00, 0x3f, 0x10, 0x00, 0x3f, 0x5e, 0x46, - 0xb3, 0x44, 0xee, 0x75, 0x19, 0xcd, 0x12, 0x9d, 0xeb, 0xf9, 0x77, 0x7c, 0x1e, 0x75, 0x3a, 0xbd, - 0xc1, 0xf4, 0x89, 0xd7, 0xc2, 0x6f, 0x9a, 0xeb, 0xf4, 0x5f, 0x02, 0xc5, 0x18, 0x1d, 0xe9, 0xd1, - 0x54, 0x9c, 0xc9, 0x17, 0x57, 0x6e, 0xb2, 0x75, 0x43, 0x64, 0x6a, 0xf8, 0x4c, 0x15, 0x2a, 0x77, - 0x9a, 0x69, 0x6c, 0x3a, 0xe9, 0x8f, 0x04, 0x4a, 0x71, 0x17, 0xb4, 0x8c, 0x56, 0x4d, 0xb9, 0x8b, - 0x66, 0xb4, 0x6a, 0xda, 0x6d, 0x90, 0xaf, 0xf9, 0x0a, 0x1c, 0xa1, 0xcf, 0x24, 0x29, 0x90, 0x9a, - 0x4f, 0xab, 0x3f, 0x53, 0xef, 0x35, 0x19, 0xfd, 0x99, 0xe7, 0x52, 0x97, 0xd1, 0x9f, 0xb9, 0xae, - 0x55, 0x39, 0xfb, 0xd3, 0xa3, 0x97, 0x33, 0xa1, 0x8c, 0x7e, 0x4f, 0x60, 0x6b, 0x68, 0x6c, 0xa7, - 0x87, 0x52, 0xd1, 0xc6, 0xdd, 0x91, 0xb8, 0x89, 0x56, 0x4c, 0x90, 0xd0, 0x79, 0x9f, 0xd0, 0x0b, - 0xb4, 0xd6, 0x0e, 0x21, 0x23, 0x04, 0xfb, 0x3e, 0x81, 0x62, 0xcc, 0xc0, 0x9b, 0xd1, 0x99, 0xc9, - 0x93, 0x3d, 0x37, 0xd9, 0xba, 0x21, 0x52, 0x3b, 0xeb, 0x53, 0x3b, 0x49, 0x8f, 0xb7, 0x43, 0x2d, - 0xf0, 0x32, 0x5f, 0x23, 0x40, 0xa3, 0xc1, 0xe8, 0x91, 0x16, 0xd1, 0xb9, 0xac, 0x8e, 0xb6, 0x6c, - 0x87, 0xa4, 0xde, 0xf6, 0x49, 0x5d, 0xa0, 0xaf, 0x6c, 0x8c, 0x54, 0x74, 0x06, 0xf8, 0x96, 0xc0, - 0xb6, 0xf0, 0x50, 0x49, 0xd3, 0x8b, 0x2a, 0x76, 0xf2, 0xe5, 0x0e, 0xb7, 0x64, 0x13, 0x9d, 0x60, - 0x26, 0xe8, 0xc1, 0x24, 0x66, 0x0b, 0x9e, 0xb1, 0xfd, 0xf3, 0x92, 0x78, 0xcd, 0x19, 0xaa, 0xaf, - 0xdf, 0x28, 0x10, 0xfa, 0x3e, 0x81, 0x3e, 0x6b, 0x4a, 0xa5, 0xa3, 0xa9, 0xf1, 0x03, 0x03, 0x31, - 0xb7, 0x3f, 0xc7, 0x4e, 0xc4, 0xb7, 0xdf, 0xc7, 0x57, 0xa1, 0xc3, 0x49, 0xf8, 0xac, 0xa1, 0x98, - 0x7e, 0x48, 0xa0, 0xdf, 0x19, 0x61, 0xe9, 0x58, 0x7a, 0x80, 0xe0, 0xd4, 0xcc, 0x1d, 0xc8, 0xb5, - 0x17, 0xe1, 0x1c, 0xf0, 0xe1, 0x54, 0x69, 0x25, 0x11, 0x8e, 0x33, 0x48, 0x1f, 0xb9, 0xf3, 0xb0, - 0x42, 0xee, 0x3e, 0xac, 0x90, 0x3f, 0x1e, 0x56, 0xc8, 0x47, 0x6b, 0x95, 0x9e, 0xbb, 0x6b, 0x95, - 0x9e, 0x5f, 0xd6, 0x2a, 0x3d, 0x6f, 0x0e, 0x3b, 0x86, 0xac, 0x71, 0x49, 0x50, 0x75, 0xd1, 0xfb, - 0xe5, 0x50, 0x34, 0xaf, 0x36, 0x65, 0x36, 0xd7, 0x6f, 0xff, 0x46, 0x7a, 0xf8, 0xff, 0x00, 0x00, - 0x00, 0xff, 0xff, 0x02, 0x10, 0x70, 0xd8, 0x32, 0x1e, 0x00, 0x00, + 0xad, 0x69, 0x6a, 0x66, 0xda, 0x54, 0xdb, 0x58, 0xa1, 0xed, 0xc6, 0xa2, 0xad, 0x2d, 0x6d, 0xba, + 0x62, 0x15, 0x3f, 0x08, 0x93, 0xec, 0x74, 0x76, 0xe8, 0x66, 0x66, 0x3b, 0x77, 0x12, 0x5a, 0x4a, + 0x11, 0x7c, 0x90, 0xfa, 0x22, 0x82, 0xef, 0xd2, 0x47, 0x11, 0x05, 0xc1, 0x54, 0x10, 0xd1, 0x47, + 0xe9, 0x83, 0x48, 0xa9, 0x54, 0xd4, 0x87, 0x2a, 0x89, 0xa0, 0x2f, 0xfe, 0x07, 0x22, 0x32, 0x33, + 0x67, 0xbe, 0x32, 0x1f, 0x3b, 0xbb, 0xd9, 0x85, 0xf4, 0x25, 0x64, 0xef, 0xdc, 0x73, 0xce, 0xef, + 0xf7, 0x3b, 0xe7, 0xdc, 0x39, 0x77, 0x17, 0xf8, 0x05, 0x9d, 0x2d, 0xea, 0x4c, 0x64, 0xa6, 0x74, + 0x45, 0xd5, 0x14, 0x71, 0xf9, 0xd0, 0xbc, 0x6c, 0x4a, 0x87, 0xc4, 0xab, 0x4b, 0xb2, 0x71, 0x5d, + 0x68, 0x1a, 0xba, 0xa9, 0xd3, 0x11, 0x67, 0x8f, 0x80, 0x7b, 0x04, 0xdc, 0xc3, 0x4d, 0xa0, 0xed, + 0xbc, 0xc4, 0x64, 0xc7, 0xc0, 0x33, 0x6f, 0x4a, 0x8a, 0xaa, 0x49, 0xa6, 0xaa, 0x6b, 0x8e, 0x0f, + 0xae, 0xa0, 0xe8, 0x8a, 0x6e, 0xff, 0x2b, 0x5a, 0xff, 0xe1, 0xea, 0xa8, 0xa2, 0xeb, 0x4a, 0x43, + 0x16, 0xa5, 0xa6, 0x2a, 0x4a, 0x9a, 0xa6, 0x9b, 0xb6, 0x09, 0xc3, 0xa7, 0x7b, 0x13, 0xb0, 0xb9, + 0x38, 0x9c, 0x5d, 0x3b, 0x9d, 0x5d, 0x73, 0x8e, 0x73, 0x84, 0xea, 0x3c, 0xda, 0x85, 0x0e, 0x5c, + 0x6c, 0x41, 0x56, 0xdc, 0x76, 0x69, 0x51, 0xd5, 0x74, 0xd1, 0xfe, 0xeb, 0x2c, 0xf1, 0xd7, 0x60, + 0xe4, 0xa2, 0xb5, 0xe3, 0x92, 0xd4, 0x50, 0x6b, 0x92, 0xa9, 0x1b, 0xac, 0x2a, 0x5f, 0x5d, 0x92, + 0x99, 0x49, 0x47, 0x60, 0x90, 0x99, 0x92, 0xb9, 0xc4, 0x8a, 0xa4, 0x4c, 0xc6, 0x87, 0xaa, 0xf8, + 0x89, 0xbe, 0x08, 0xe0, 0x53, 0x2d, 0xe6, 0xca, 0x64, 0x7c, 0xcb, 0xd4, 0x3e, 0x01, 0x41, 0x58, + 0xba, 0x08, 0x4e, 0x48, 0x84, 0x2e, 0xcc, 0x4a, 0x8a, 0x8c, 0x3e, 0xab, 0x01, 0x4b, 0xbe, 0x0e, + 0x5b, 0xbd, 0xa0, 0x67, 0xb4, 0xcb, 0x3a, 0xad, 0xc0, 0xf6, 0x05, 0x5d, 0x63, 0xb2, 0xc6, 0x96, + 0xd8, 0x9c, 0x54, 0xab, 0x19, 0x32, 0xc3, 0xd8, 0x33, 0x85, 0xdf, 0x56, 0x26, 0x87, 0xaf, 0xb9, + 0x2a, 0x94, 0x97, 0x0f, 0x0a, 0x53, 0xc2, 0xc1, 0xea, 0xb0, 0xb7, 0xbd, 0xe2, 0xec, 0x3e, 0x56, + 0xb8, 0x1f, 0xb3, 0x8f, 0x7f, 0x3f, 0x07, 0x4f, 0x44, 0x48, 0xb2, 0xa6, 0x65, 0x4c, 0xcf, 0x01, + 0x2c, 0x7b, 0xab, 0x45, 0x52, 0xee, 0x1f, 0xdf, 0x32, 0xb5, 0x47, 0x88, 0xcf, 0xbe, 0xe0, 0xd9, + 0xcf, 0x0c, 0xdd, 0x7d, 0x38, 0xd6, 0xf7, 0xc9, 0x5f, 0x5f, 0x4c, 0x90, 0x6a, 0xc0, 0x9e, 0xbe, + 0x06, 0xdb, 0xbc, 0x4f, 0x73, 0xaa, 0x76, 0x59, 0x2f, 0xe6, 0x6c, 0x8f, 0x4f, 0xb6, 0xf4, 0x68, + 0x29, 0x10, 0xf4, 0xba, 0x75, 0x39, 0xa4, 0xcd, 0x4b, 0x21, 0xd1, 0xfb, 0x6d, 0xd1, 0x9f, 0x6a, + 0x29, 0xba, 0xc3, 0x31, 0xa4, 0xba, 0x04, 0x3b, 0xc2, 0x52, 0xb8, 0xe9, 0x3e, 0x1d, 0x84, 0x6e, + 0xa9, 0x8f, 0xd2, 0xef, 0xb9, 0xbf, 0x32, 0xb9, 0x1b, 0x03, 0x79, 0x46, 0xa8, 0xf7, 0x2b, 0xa6, + 0xa1, 0x6a, 0x4a, 0x00, 0xab, 0xb5, 0xce, 0xd7, 0xd6, 0x97, 0x94, 0x27, 0xf6, 0xcb, 0x30, 0xe4, + 0x6d, 0xb5, 0xdd, 0xb7, 0xab, 0xb5, 0x6f, 0xce, 0xaf, 0x10, 0x28, 0x87, 0xc3, 0x9c, 0x92, 0x1b, + 0xb2, 0xe2, 0x74, 0x53, 0xd7, 0x49, 0x75, 0xad, 0xea, 0xff, 0x21, 0xb0, 0x27, 0x05, 0x36, 0x0a, + 0xf5, 0x0e, 0x14, 0x6a, 0xde, 0xf2, 0x9c, 0x81, 0xcb, 0x6e, 0x7d, 0x4e, 0x24, 0x69, 0xe6, 0xbb, + 0x72, 0x3d, 0xcd, 0x94, 0x2d, 0xf1, 0x3e, 0xfd, 0x7d, 0x2c, 0x1f, 0x7d, 0xc6, 0x1c, 0x4d, 0xf3, + 0xb5, 0xe8, 0x93, 0x75, 0xf5, 0x96, 0xeb, 0xbc, 0xde, 0xbe, 0x25, 0xb0, 0x3f, 0xcc, 0xf7, 0x55, + 0x6d, 0x5e, 0xd7, 0x6a, 0xaa, 0xa6, 0x3c, 0x12, 0xf9, 0x7a, 0x48, 0x60, 0x22, 0x0b, 0x7e, 0x4c, + 0x9c, 0x02, 0xf9, 0x25, 0xf7, 0x79, 0x24, 0x6f, 0x07, 0x92, 0xf2, 0x16, 0xe3, 0x32, 0x58, 0xf5, + 0xd4, 0x73, 0xd9, 0x83, 0x04, 0x7d, 0x4e, 0xb0, 0x5d, 0x83, 0x05, 0xe2, 0x64, 0xe3, 0x04, 0x6c, + 0xc3, 0xda, 0x08, 0x67, 0xa3, 0x78, 0x7f, 0x65, 0xb2, 0x80, 0xa1, 0xd6, 0x25, 0xc1, 0xdb, 0x6f, + 0x27, 0x21, 0x9a, 0xce, 0x5c, 0x67, 0xe9, 0x3c, 0xf6, 0xf8, 0xad, 0xdb, 0x63, 0x7d, 0x7f, 0xdf, + 0x1e, 0xeb, 0xe3, 0x97, 0xf1, 0x2c, 0x8f, 0xd6, 0x33, 0x7d, 0x13, 0xf2, 0x31, 0x5d, 0x83, 0x07, + 0x4d, 0x1b, 0x4d, 0x53, 0xa5, 0xd1, 0x96, 0xe0, 0xbf, 0x22, 0x30, 0x66, 0x07, 0x8e, 0x49, 0xd6, + 0xa6, 0x16, 0xcc, 0xc0, 0x73, 0x32, 0x16, 0x37, 0x2a, 0x77, 0x1e, 0x06, 0x9d, 0x1a, 0x43, 0xb1, + 0x3a, 0xad, 0x54, 0xf4, 0xc2, 0xdf, 0x71, 0x0f, 0xe7, 0x53, 0x2e, 0xbd, 0x98, 0x66, 0xdf, 0xb0, + 0x5a, 0x5d, 0xea, 0xf1, 0x80, 0x56, 0x3f, 0xbb, 0xa7, 0x73, 0x3c, 0x6e, 0x54, 0xab, 0xde, 0xb5, + 0xd3, 0x39, 0x20, 0x5d, 0x6f, 0x8f, 0xe1, 0xef, 0xdc, 0x63, 0xd8, 0x23, 0x96, 0x76, 0x0c, 0x6f, + 0xc2, 0xcc, 0x78, 0xe7, 0x70, 0x0b, 0x02, 0x8f, 0xec, 0x39, 0x7c, 0x2f, 0x07, 0x3b, 0x6d, 0x82, + 0x55, 0xb9, 0xd6, 0x83, 0x8c, 0x5c, 0x00, 0xca, 0x8c, 0x85, 0xb9, 0x4e, 0x4f, 0x97, 0x61, 0x66, + 0x2c, 0x84, 0x1e, 0x59, 0x0e, 0x6b, 0xcc, 0x5c, 0xef, 0xb0, 0x3f, 0xb3, 0xc3, 0x1a, 0x33, 0x2f, + 0xa5, 0xbc, 0xb1, 0x07, 0xba, 0x50, 0x33, 0x0f, 0x08, 0x70, 0x71, 0x92, 0x62, 0x8d, 0x68, 0x30, + 0x62, 0xc8, 0x29, 0x8d, 0xfc, 0x74, 0x52, 0x99, 0x04, 0xdd, 0xc5, 0xb5, 0xf2, 0x0e, 0x43, 0xee, + 0x69, 0x33, 0xaf, 0xb8, 0xaf, 0x22, 0xaf, 0x17, 0xa2, 0xb7, 0xb7, 0x4d, 0xd8, 0xc2, 0x5f, 0x47, + 0x5e, 0x0a, 0x3d, 0xbf, 0x8f, 0x75, 0x4d, 0xf2, 0x3b, 0x04, 0x4a, 0x09, 0xd8, 0x37, 0xf5, 0xcb, + 0x7f, 0x31, 0xb1, 0x52, 0x7a, 0x72, 0x29, 0x9b, 0xc6, 0x86, 0x3b, 0xad, 0x32, 0x53, 0x37, 0xd4, + 0x05, 0xa9, 0x61, 0xdd, 0x5e, 0x03, 0xdf, 0x28, 0xd4, 0x65, 0x55, 0xa9, 0x9b, 0x76, 0x98, 0xfe, + 0x2a, 0x7e, 0x3a, 0x96, 0x2b, 0x12, 0x5e, 0x82, 0x5d, 0xb1, 0x96, 0x08, 0xf2, 0x38, 0x0c, 0xd4, + 0x55, 0x66, 0x22, 0xbe, 0x7d, 0x49, 0xf8, 0xc2, 0xd6, 0x33, 0xb9, 0x22, 0xa9, 0xda, 0x76, 0x76, + 0x08, 0x0a, 0xc3, 0x76, 0x88, 0x59, 0x5d, 0x6f, 0x20, 0x24, 0x7e, 0x16, 0xb6, 0x07, 0xd6, 0x30, + 0xd8, 0xf3, 0x30, 0xd0, 0xd4, 0xf5, 0x06, 0x06, 0x1b, 0x4d, 0x0a, 0x66, 0xd9, 0x04, 0x75, 0xb0, + 0x8d, 0xf8, 0x02, 0x50, 0xc7, 0xa3, 0x64, 0x48, 0x8b, 0x6e, 0x3b, 0xf2, 0xaf, 0x43, 0x3e, 0xb4, + 0x8a, 0x91, 0x2a, 0x30, 0xd8, 0xb4, 0x57, 0x30, 0x56, 0x29, 0x31, 0x96, 0xbd, 0x2b, 0x34, 0x6a, + 0x39, 0x86, 0x53, 0x5f, 0x8e, 0xc0, 0x63, 0xb6, 0x6b, 0xfa, 0x31, 0x01, 0xf0, 0x3b, 0x8a, 0x0a, + 0x49, 0xbe, 0xe2, 0xbf, 0xef, 0xe1, 0xc4, 0xcc, 0xfb, 0x71, 0x22, 0x16, 0x6f, 0x59, 0x40, 0xde, + 0xfd, 0xe9, 0xcf, 0x8f, 0x72, 0x7b, 0x29, 0x2f, 0x26, 0x7c, 0x73, 0x15, 0xe8, 0xc6, 0xcf, 0x08, + 0x0c, 0x79, 0x7e, 0xe8, 0x64, 0xb6, 0x78, 0x2e, 0x3c, 0x21, 0xeb, 0x76, 0x44, 0x77, 0xd2, 0x47, + 0xf7, 0x2c, 0x3d, 0xdc, 0x1a, 0x9d, 0x78, 0x23, 0xdc, 0x7c, 0x37, 0xe9, 0xaf, 0x04, 0x0a, 0x71, + 0xb7, 0x74, 0x3a, 0x9d, 0x0d, 0x4a, 0x74, 0xb0, 0xe2, 0x9e, 0xeb, 0xc0, 0x12, 0xf9, 0x9c, 0xf3, + 0xf9, 0x54, 0xe8, 0x89, 0x0e, 0xf8, 0x88, 0x81, 0x77, 0x20, 0xfd, 0x8f, 0xc0, 0xee, 0xd4, 0x1b, + 0x2d, 0xad, 0x64, 0x83, 0x9a, 0x32, 0x46, 0x72, 0x33, 0x1b, 0x71, 0x81, 0xb4, 0x2f, 0xf9, 0xb4, + 0xcf, 0xd2, 0x33, 0x9d, 0xd0, 0xf6, 0xe7, 0xc0, 0xa0, 0x00, 0x3f, 0x10, 0x00, 0x3f, 0x5e, 0x8b, + 0x66, 0x89, 0xdc, 0xf4, 0x5a, 0x34, 0x4b, 0x74, 0xd2, 0xe7, 0xdf, 0xf6, 0x79, 0x54, 0xe9, 0xec, + 0x06, 0xd3, 0x27, 0xde, 0x08, 0xbf, 0x69, 0x6e, 0xd2, 0x7f, 0x09, 0xe4, 0x63, 0x74, 0xa4, 0x47, + 0x53, 0x71, 0x26, 0x5f, 0x65, 0xb9, 0xe9, 0xf6, 0x0d, 0x91, 0xa9, 0xe1, 0x33, 0x55, 0xa8, 0xdc, + 0x6d, 0xa6, 0xb1, 0xe9, 0xa4, 0x3f, 0x12, 0x28, 0xc4, 0x5d, 0xd9, 0x5a, 0xb4, 0x6a, 0xca, 0xed, + 0xb4, 0x45, 0xab, 0xa6, 0xdd, 0x0f, 0xf9, 0x8a, 0xaf, 0xc0, 0x11, 0xfa, 0x4c, 0x92, 0x02, 0xa9, + 0xf9, 0xb4, 0xfa, 0x33, 0xf5, 0xa6, 0xd3, 0xa2, 0x3f, 0xb3, 0x5c, 0xf3, 0x5a, 0xf4, 0x67, 0xa6, + 0x8b, 0x56, 0xc6, 0xfe, 0xf4, 0xe8, 0x65, 0x4c, 0x28, 0xa3, 0xdf, 0x13, 0xd8, 0x1a, 0x1a, 0xdb, + 0xe9, 0xa1, 0x54, 0xb4, 0x71, 0xb7, 0x26, 0x6e, 0xaa, 0x1d, 0x13, 0x24, 0x74, 0xde, 0x27, 0xf4, + 0x02, 0xad, 0x74, 0x42, 0xc8, 0x08, 0xc1, 0x7e, 0x40, 0x20, 0x1f, 0x33, 0xf0, 0xb6, 0xe8, 0xcc, + 0xe4, 0xc9, 0x9e, 0x9b, 0x6e, 0xdf, 0x10, 0xa9, 0x9d, 0xf5, 0xa9, 0x9d, 0xa4, 0xc7, 0x3b, 0xa1, + 0x16, 0x78, 0x99, 0xaf, 0x11, 0xa0, 0xd1, 0x60, 0xf4, 0x48, 0x9b, 0xe8, 0x5c, 0x56, 0x47, 0xdb, + 0xb6, 0x43, 0x52, 0x6f, 0xf9, 0xa4, 0x2e, 0xd2, 0x0b, 0x1b, 0x23, 0x15, 0x9d, 0x01, 0xbe, 0x21, + 0xb0, 0x2d, 0x3c, 0x54, 0xd2, 0xf4, 0xa2, 0x8a, 0x9d, 0x7c, 0xb9, 0xc3, 0x6d, 0xd9, 0x44, 0x27, + 0x98, 0x29, 0x7a, 0x30, 0x89, 0x59, 0xdd, 0x33, 0xb6, 0x7f, 0x70, 0x12, 0x6f, 0x38, 0x43, 0xf5, + 0xcd, 0x5b, 0x39, 0x42, 0xdf, 0x23, 0x30, 0x60, 0x4d, 0xa9, 0x74, 0x3c, 0x35, 0x7e, 0x60, 0x20, + 0xe6, 0xf6, 0x67, 0xd8, 0x89, 0xf8, 0xf6, 0xfb, 0xf8, 0x4a, 0x74, 0x34, 0x09, 0x9f, 0x35, 0x14, + 0xd3, 0x0f, 0x08, 0x0c, 0x3a, 0x23, 0x2c, 0x9d, 0x48, 0x0f, 0x10, 0x9c, 0x9a, 0xb9, 0x03, 0x99, + 0xf6, 0x22, 0x9c, 0x03, 0x3e, 0x9c, 0x32, 0x2d, 0x25, 0xc2, 0x71, 0x06, 0xe9, 0x23, 0x77, 0x57, + 0x4b, 0xe4, 0xde, 0x6a, 0x89, 0xfc, 0xb1, 0x5a, 0x22, 0x1f, 0xae, 0x95, 0xfa, 0xee, 0xad, 0x95, + 0xfa, 0x7e, 0x59, 0x2b, 0xf5, 0xbd, 0x31, 0xea, 0x18, 0xb2, 0xda, 0x15, 0x41, 0xd5, 0x45, 0xef, + 0xb7, 0x44, 0xd1, 0xbc, 0xde, 0x94, 0xd9, 0xfc, 0xa0, 0xfd, 0xab, 0xe9, 0xe1, 0xff, 0x03, 0x00, + 0x00, 0xff, 0xff, 0x98, 0x4e, 0x1d, 0xaa, 0x44, 0x1e, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. diff --git a/x/staking/types/staking.pb.go b/x/staking/types/staking.pb.go index d6511264f7c3..197e937a35d4 100644 --- a/x/staking/types/staking.pb.go +++ b/x/staking/types/staking.pb.go @@ -270,6 +270,8 @@ type Description struct { SecurityContact string `protobuf:"bytes,4,opt,name=security_contact,json=securityContact,proto3" json:"security_contact,omitempty"` // details define other optional details. Details string `protobuf:"bytes,5,opt,name=details,proto3" json:"details,omitempty"` + // metadata defines extra information about the validator. + Metadata Metadata `protobuf:"bytes,6,opt,name=metadata,proto3" json:"metadata"` } func (m *Description) Reset() { *m = Description{} } @@ -340,6 +342,68 @@ func (m *Description) GetDetails() string { return "" } +func (m *Description) GetMetadata() Metadata { + if m != nil { + return m.Metadata + } + return Metadata{} +} + +// Metadata defines extra information about the validator. +type Metadata struct { + // profile_pic_uri defines a link to the validator profile picture. + ProfilePicUri string `protobuf:"bytes,1,opt,name=profile_pic_uri,json=profilePicUri,proto3" json:"profile_pic_uri,omitempty"` + // social_handle_uris defines a string array of uris to the validator's social handles. + SocialHandleUris []string `protobuf:"bytes,2,rep,name=social_handle_uris,json=socialHandleUris,proto3" json:"social_handle_uris,omitempty"` +} + +func (m *Metadata) Reset() { *m = Metadata{} } +func (m *Metadata) String() string { return proto.CompactTextString(m) } +func (*Metadata) ProtoMessage() {} +func (*Metadata) Descriptor() ([]byte, []int) { + return fileDescriptor_64c30c6cf92913c9, []int{4} +} +func (m *Metadata) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *Metadata) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_Metadata.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 *Metadata) XXX_Merge(src proto.Message) { + xxx_messageInfo_Metadata.Merge(m, src) +} +func (m *Metadata) XXX_Size() int { + return m.Size() +} +func (m *Metadata) XXX_DiscardUnknown() { + xxx_messageInfo_Metadata.DiscardUnknown(m) +} + +var xxx_messageInfo_Metadata proto.InternalMessageInfo + +func (m *Metadata) GetProfilePicUri() string { + if m != nil { + return m.ProfilePicUri + } + return "" +} + +func (m *Metadata) GetSocialHandleUris() []string { + if m != nil { + return m.SocialHandleUris + } + return nil +} + // Validator defines a validator, together with the total amount of the // Validator's bond shares and their exchange rate to coins. Slashing results in // a decrease in the exchange rate, allowing correct calculation of future @@ -381,7 +445,7 @@ func (m *Validator) Reset() { *m = Validator{} } func (m *Validator) String() string { return proto.CompactTextString(m) } func (*Validator) ProtoMessage() {} func (*Validator) Descriptor() ([]byte, []int) { - return fileDescriptor_64c30c6cf92913c9, []int{4} + return fileDescriptor_64c30c6cf92913c9, []int{5} } func (m *Validator) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -419,7 +483,7 @@ func (m *ValAddresses) Reset() { *m = ValAddresses{} } func (m *ValAddresses) String() string { return proto.CompactTextString(m) } func (*ValAddresses) ProtoMessage() {} func (*ValAddresses) Descriptor() ([]byte, []int) { - return fileDescriptor_64c30c6cf92913c9, []int{5} + return fileDescriptor_64c30c6cf92913c9, []int{6} } func (m *ValAddresses) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -467,7 +531,7 @@ func (m *DVPair) Reset() { *m = DVPair{} } func (m *DVPair) String() string { return proto.CompactTextString(m) } func (*DVPair) ProtoMessage() {} func (*DVPair) Descriptor() ([]byte, []int) { - return fileDescriptor_64c30c6cf92913c9, []int{6} + return fileDescriptor_64c30c6cf92913c9, []int{7} } func (m *DVPair) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -505,7 +569,7 @@ func (m *DVPairs) Reset() { *m = DVPairs{} } func (m *DVPairs) String() string { return proto.CompactTextString(m) } func (*DVPairs) ProtoMessage() {} func (*DVPairs) Descriptor() ([]byte, []int) { - return fileDescriptor_64c30c6cf92913c9, []int{7} + return fileDescriptor_64c30c6cf92913c9, []int{8} } func (m *DVPairs) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -555,7 +619,7 @@ func (m *DVVTriplet) Reset() { *m = DVVTriplet{} } func (m *DVVTriplet) String() string { return proto.CompactTextString(m) } func (*DVVTriplet) ProtoMessage() {} func (*DVVTriplet) Descriptor() ([]byte, []int) { - return fileDescriptor_64c30c6cf92913c9, []int{8} + return fileDescriptor_64c30c6cf92913c9, []int{9} } func (m *DVVTriplet) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -593,7 +657,7 @@ func (m *DVVTriplets) Reset() { *m = DVVTriplets{} } func (m *DVVTriplets) String() string { return proto.CompactTextString(m) } func (*DVVTriplets) ProtoMessage() {} func (*DVVTriplets) Descriptor() ([]byte, []int) { - return fileDescriptor_64c30c6cf92913c9, []int{9} + return fileDescriptor_64c30c6cf92913c9, []int{10} } func (m *DVVTriplets) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -645,7 +709,7 @@ func (m *Delegation) Reset() { *m = Delegation{} } func (m *Delegation) String() string { return proto.CompactTextString(m) } func (*Delegation) ProtoMessage() {} func (*Delegation) Descriptor() ([]byte, []int) { - return fileDescriptor_64c30c6cf92913c9, []int{10} + return fileDescriptor_64c30c6cf92913c9, []int{11} } func (m *Delegation) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -689,7 +753,7 @@ func (m *UnbondingDelegation) Reset() { *m = UnbondingDelegation{} } func (m *UnbondingDelegation) String() string { return proto.CompactTextString(m) } func (*UnbondingDelegation) ProtoMessage() {} func (*UnbondingDelegation) Descriptor() ([]byte, []int) { - return fileDescriptor_64c30c6cf92913c9, []int{11} + return fileDescriptor_64c30c6cf92913c9, []int{12} } func (m *UnbondingDelegation) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -738,7 +802,7 @@ func (m *UnbondingDelegationEntry) Reset() { *m = UnbondingDelegationEnt func (m *UnbondingDelegationEntry) String() string { return proto.CompactTextString(m) } func (*UnbondingDelegationEntry) ProtoMessage() {} func (*UnbondingDelegationEntry) Descriptor() ([]byte, []int) { - return fileDescriptor_64c30c6cf92913c9, []int{12} + return fileDescriptor_64c30c6cf92913c9, []int{13} } func (m *UnbondingDelegationEntry) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -815,7 +879,7 @@ func (m *RedelegationEntry) Reset() { *m = RedelegationEntry{} } func (m *RedelegationEntry) String() string { return proto.CompactTextString(m) } func (*RedelegationEntry) ProtoMessage() {} func (*RedelegationEntry) Descriptor() ([]byte, []int) { - return fileDescriptor_64c30c6cf92913c9, []int{13} + return fileDescriptor_64c30c6cf92913c9, []int{14} } func (m *RedelegationEntry) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -889,7 +953,7 @@ func (m *Redelegation) Reset() { *m = Redelegation{} } func (m *Redelegation) String() string { return proto.CompactTextString(m) } func (*Redelegation) ProtoMessage() {} func (*Redelegation) Descriptor() ([]byte, []int) { - return fileDescriptor_64c30c6cf92913c9, []int{14} + return fileDescriptor_64c30c6cf92913c9, []int{15} } func (m *Redelegation) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -941,7 +1005,7 @@ func (m *Params) Reset() { *m = Params{} } func (m *Params) String() string { return proto.CompactTextString(m) } func (*Params) ProtoMessage() {} func (*Params) Descriptor() ([]byte, []int) { - return fileDescriptor_64c30c6cf92913c9, []int{15} + return fileDescriptor_64c30c6cf92913c9, []int{16} } func (m *Params) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1024,7 +1088,7 @@ func (m *DelegationResponse) Reset() { *m = DelegationResponse{} } func (m *DelegationResponse) String() string { return proto.CompactTextString(m) } func (*DelegationResponse) ProtoMessage() {} func (*DelegationResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_64c30c6cf92913c9, []int{16} + return fileDescriptor_64c30c6cf92913c9, []int{17} } func (m *DelegationResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1079,7 +1143,7 @@ func (m *RedelegationEntryResponse) Reset() { *m = RedelegationEntryResp func (m *RedelegationEntryResponse) String() string { return proto.CompactTextString(m) } func (*RedelegationEntryResponse) ProtoMessage() {} func (*RedelegationEntryResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_64c30c6cf92913c9, []int{17} + return fileDescriptor_64c30c6cf92913c9, []int{18} } func (m *RedelegationEntryResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1127,7 +1191,7 @@ func (m *RedelegationResponse) Reset() { *m = RedelegationResponse{} } func (m *RedelegationResponse) String() string { return proto.CompactTextString(m) } func (*RedelegationResponse) ProtoMessage() {} func (*RedelegationResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_64c30c6cf92913c9, []int{18} + return fileDescriptor_64c30c6cf92913c9, []int{19} } func (m *RedelegationResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1181,7 +1245,7 @@ func (m *Pool) Reset() { *m = Pool{} } func (m *Pool) String() string { return proto.CompactTextString(m) } func (*Pool) ProtoMessage() {} func (*Pool) Descriptor() ([]byte, []int) { - return fileDescriptor_64c30c6cf92913c9, []int{19} + return fileDescriptor_64c30c6cf92913c9, []int{20} } func (m *Pool) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1222,7 +1286,7 @@ func (m *ValidatorUpdates) Reset() { *m = ValidatorUpdates{} } func (m *ValidatorUpdates) String() string { return proto.CompactTextString(m) } func (*ValidatorUpdates) ProtoMessage() {} func (*ValidatorUpdates) Descriptor() ([]byte, []int) { - return fileDescriptor_64c30c6cf92913c9, []int{20} + return fileDescriptor_64c30c6cf92913c9, []int{21} } func (m *ValidatorUpdates) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1276,7 +1340,7 @@ func (m *ConsPubKeyRotationHistory) Reset() { *m = ConsPubKeyRotationHis func (m *ConsPubKeyRotationHistory) String() string { return proto.CompactTextString(m) } func (*ConsPubKeyRotationHistory) ProtoMessage() {} func (*ConsPubKeyRotationHistory) Descriptor() ([]byte, []int) { - return fileDescriptor_64c30c6cf92913c9, []int{21} + return fileDescriptor_64c30c6cf92913c9, []int{22} } func (m *ConsPubKeyRotationHistory) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1315,7 +1379,7 @@ func (m *ValAddrsOfRotatedConsKeys) Reset() { *m = ValAddrsOfRotatedCons func (m *ValAddrsOfRotatedConsKeys) String() string { return proto.CompactTextString(m) } func (*ValAddrsOfRotatedConsKeys) ProtoMessage() {} func (*ValAddrsOfRotatedConsKeys) Descriptor() ([]byte, []int) { - return fileDescriptor_64c30c6cf92913c9, []int{22} + return fileDescriptor_64c30c6cf92913c9, []int{23} } func (m *ValAddrsOfRotatedConsKeys) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1358,6 +1422,7 @@ func init() { proto.RegisterType((*CommissionRates)(nil), "cosmos.staking.v1beta1.CommissionRates") proto.RegisterType((*Commission)(nil), "cosmos.staking.v1beta1.Commission") proto.RegisterType((*Description)(nil), "cosmos.staking.v1beta1.Description") + proto.RegisterType((*Metadata)(nil), "cosmos.staking.v1beta1.Metadata") proto.RegisterType((*Validator)(nil), "cosmos.staking.v1beta1.Validator") proto.RegisterType((*ValAddresses)(nil), "cosmos.staking.v1beta1.ValAddresses") proto.RegisterType((*DVPair)(nil), "cosmos.staking.v1beta1.DVPair") @@ -1384,137 +1449,142 @@ func init() { } var fileDescriptor_64c30c6cf92913c9 = []byte{ - // 2065 bytes of a gzipped FileDescriptorProto + // 2146 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe4, 0x59, 0x4b, 0x6c, 0x1b, 0xc7, - 0x19, 0xd6, 0x92, 0x0c, 0x25, 0xfd, 0x94, 0x44, 0x6a, 0xfc, 0xa2, 0xe8, 0x58, 0x92, 0x19, 0xb7, - 0x91, 0xdd, 0x9a, 0x8a, 0xdc, 0xc2, 0x05, 0x84, 0x20, 0x85, 0x29, 0xd2, 0x31, 0xf3, 0x90, 0xd4, - 0xa5, 0xa4, 0x3e, 0xd0, 0x66, 0x31, 0xdc, 0x1d, 0x52, 0x5b, 0x91, 0xb3, 0xec, 0xce, 0x50, 0x36, - 0xef, 0x3d, 0x04, 0x2e, 0x0a, 0xe4, 0x54, 0x04, 0x28, 0x8c, 0x1a, 0xe8, 0x25, 0xbd, 0xe5, 0x60, - 0xf4, 0xde, 0x5b, 0x5a, 0xa0, 0x80, 0xe1, 0x53, 0x11, 0xa0, 0x6e, 0x61, 0x1f, 0x12, 0x34, 0x97, - 0xa2, 0xa7, 0x1e, 0x8b, 0x79, 0xec, 0x83, 0xa2, 0x68, 0x59, 0x72, 0x50, 0x04, 0xed, 0x45, 0xe0, - 0xcc, 0xfc, 0xff, 0xb7, 0xf3, 0x7f, 0xf3, 0x3f, 0x66, 0x7e, 0xc1, 0x25, 0xdb, 0x63, 0x1d, 0x8f, - 0x2d, 0x33, 0x8e, 0xf7, 0x5c, 0xda, 0x5a, 0xde, 0x5f, 0x69, 0x10, 0x8e, 0x57, 0x82, 0x71, 0xa9, - 0xeb, 0x7b, 0xdc, 0x43, 0x67, 0x95, 0x54, 0x29, 0x98, 0xd5, 0x52, 0x85, 0xd3, 0x2d, 0xaf, 0xe5, - 0x49, 0x91, 0x65, 0xf1, 0x4b, 0x49, 0x17, 0xe6, 0x5a, 0x9e, 0xd7, 0x6a, 0x93, 0x65, 0x39, 0x6a, - 0xf4, 0x9a, 0xcb, 0x98, 0xf6, 0xf5, 0xd2, 0xfc, 0xc1, 0x25, 0xa7, 0xe7, 0x63, 0xee, 0x7a, 0x54, - 0xaf, 0x2f, 0x1c, 0x5c, 0xe7, 0x6e, 0x87, 0x30, 0x8e, 0x3b, 0xdd, 0x00, 0x5b, 0xed, 0xc4, 0x52, - 0x1f, 0xd5, 0xdb, 0xd2, 0xd8, 0xda, 0x94, 0x06, 0x66, 0x24, 0xb4, 0xc3, 0xf6, 0xdc, 0x00, 0x7b, - 0x16, 0x77, 0x5c, 0xea, 0x2d, 0xcb, 0xbf, 0x7a, 0xea, 0x82, 0xed, 0x75, 0x08, 0x6f, 0x34, 0xf9, - 0x32, 0xef, 0x77, 0x09, 0x5b, 0xde, 0x5f, 0x51, 0x3f, 0xf4, 0xf2, 0xcb, 0xe1, 0x32, 0x6e, 0xd8, - 0xee, 0x81, 0xd5, 0xe2, 0x87, 0x06, 0xcc, 0xdc, 0x72, 0x19, 0xf7, 0x7c, 0xd7, 0xc6, 0xed, 0x1a, - 0x6d, 0x7a, 0xe8, 0x75, 0x48, 0xef, 0x12, 0xec, 0x10, 0x3f, 0x6f, 0x2c, 0x1a, 0x4b, 0x99, 0x6b, - 0x73, 0xa5, 0x00, 0xa1, 0xa4, 0x34, 0xf7, 0x57, 0x4a, 0xb7, 0xa4, 0x40, 0x79, 0xf2, 0x93, 0xc7, - 0x0b, 0x63, 0x1f, 0x7d, 0xf6, 0xf1, 0x15, 0xc3, 0xd4, 0x3a, 0xa8, 0x02, 0xe9, 0x7d, 0xdc, 0x66, - 0x84, 0xe7, 0x13, 0x8b, 0xc9, 0xa5, 0xcc, 0xb5, 0x8b, 0xa5, 0xc3, 0x69, 0x2f, 0xed, 0xe0, 0xb6, - 0xeb, 0x60, 0xee, 0x0d, 0xa2, 0x28, 0xdd, 0xd5, 0x44, 0xde, 0x28, 0xfe, 0x2a, 0x01, 0xd9, 0x35, - 0xaf, 0xd3, 0x71, 0x19, 0x73, 0x3d, 0x6a, 0x62, 0x4e, 0x18, 0x7a, 0x0b, 0x52, 0x3e, 0xe6, 0x44, - 0xee, 0x6c, 0xb2, 0x7c, 0x5d, 0x28, 0x7e, 0xfa, 0x78, 0xe1, 0xbc, 0xfa, 0x04, 0x73, 0xf6, 0x4a, - 0xae, 0xb7, 0xdc, 0xc1, 0x7c, 0xb7, 0xf4, 0x0e, 0x69, 0x61, 0xbb, 0x5f, 0x21, 0xf6, 0xa3, 0x07, - 0x57, 0x41, 0xef, 0xa0, 0x42, 0x6c, 0xf5, 0x15, 0x89, 0x81, 0xbe, 0x07, 0x13, 0x1d, 0x7c, 0xc7, - 0x92, 0x78, 0x89, 0x17, 0xc2, 0x1b, 0xef, 0xe0, 0x3b, 0x62, 0x7f, 0xe8, 0x3d, 0xc8, 0x0a, 0x48, - 0x7b, 0x17, 0xd3, 0x16, 0x51, 0xc8, 0xc9, 0x17, 0x42, 0x9e, 0xee, 0xe0, 0x3b, 0x6b, 0x12, 0x4d, - 0xe0, 0xaf, 0xa6, 0x3e, 0xbf, 0xbf, 0x60, 0x14, 0xff, 0x60, 0x00, 0x44, 0xc4, 0x20, 0x0c, 0x39, - 0x3b, 0x1c, 0xc9, 0x8f, 0x32, 0x7d, 0x72, 0xaf, 0x8e, 0xe2, 0xfe, 0x00, 0xad, 0xe5, 0x69, 0xb1, - 0xbd, 0x87, 0x8f, 0x17, 0x0c, 0xf5, 0xd5, 0xac, 0x3d, 0x44, 0x7b, 0xa6, 0xd7, 0x75, 0x30, 0x27, - 0x96, 0x70, 0x65, 0xc9, 0x56, 0xe6, 0x5a, 0xa1, 0xa4, 0xfc, 0xbc, 0x14, 0xf8, 0x79, 0x69, 0x2b, - 0xf0, 0x73, 0x05, 0xf8, 0xc1, 0xdf, 0x02, 0x40, 0x50, 0xda, 0x62, 0x5d, 0xdb, 0xf0, 0x91, 0x01, - 0x99, 0x0a, 0x61, 0xb6, 0xef, 0x76, 0x45, 0xe4, 0xa0, 0x3c, 0x8c, 0x77, 0x3c, 0xea, 0xee, 0x69, - 0xaf, 0x9b, 0x34, 0x83, 0x21, 0x2a, 0xc0, 0x84, 0xeb, 0x10, 0xca, 0x5d, 0xde, 0x57, 0xc7, 0x64, - 0x86, 0x63, 0xa1, 0x75, 0x9b, 0x34, 0x98, 0x1b, 0xf0, 0x6c, 0x06, 0x43, 0x74, 0x19, 0x72, 0x8c, - 0xd8, 0x3d, 0xdf, 0xe5, 0x7d, 0xcb, 0xf6, 0x28, 0xc7, 0x36, 0xcf, 0xa7, 0xa4, 0x48, 0x36, 0x98, - 0x5f, 0x53, 0xd3, 0x02, 0xc4, 0x21, 0x1c, 0xbb, 0x6d, 0x96, 0x7f, 0x49, 0x81, 0xe8, 0xa1, 0xde, - 0xea, 0xbd, 0x71, 0x98, 0x0c, 0x9d, 0x15, 0xad, 0x41, 0xce, 0xeb, 0x12, 0x5f, 0xfc, 0xb6, 0xb0, - 0xe3, 0xf8, 0x84, 0x31, 0xed, 0x8d, 0xf9, 0x47, 0x0f, 0xae, 0x9e, 0xd6, 0x84, 0xdf, 0x50, 0x2b, - 0x75, 0xee, 0xbb, 0xb4, 0x65, 0x66, 0x03, 0x0d, 0x3d, 0x8d, 0x7e, 0x28, 0x8e, 0x8c, 0x32, 0x42, - 0x59, 0x8f, 0x59, 0xdd, 0x5e, 0x63, 0x8f, 0xf4, 0x35, 0xa9, 0xa7, 0x87, 0x48, 0xbd, 0x41, 0xfb, - 0xe5, 0xfc, 0x9f, 0x22, 0x68, 0xdb, 0xef, 0x77, 0xb9, 0x57, 0xda, 0xec, 0x35, 0xde, 0x26, 0x7d, - 0x71, 0x54, 0x1a, 0x67, 0x53, 0xc2, 0xa0, 0xb3, 0x90, 0xfe, 0x29, 0x76, 0xdb, 0xc4, 0x91, 0x8c, - 0x4c, 0x98, 0x7a, 0x84, 0x56, 0x21, 0xcd, 0x38, 0xe6, 0x3d, 0x26, 0x69, 0x98, 0xb9, 0x56, 0x1c, - 0xe5, 0x1b, 0x65, 0x8f, 0x3a, 0x75, 0x29, 0x69, 0x6a, 0x0d, 0xb4, 0x06, 0x69, 0xee, 0xed, 0x11, - 0xaa, 0x09, 0x2a, 0x7f, 0x43, 0x7b, 0xf3, 0x99, 0x61, 0x6f, 0xae, 0x51, 0x1e, 0xf3, 0xe3, 0x1a, - 0xe5, 0xa6, 0x56, 0x45, 0x3f, 0x86, 0x9c, 0x43, 0xda, 0xa4, 0x25, 0x99, 0x63, 0xbb, 0xd8, 0x27, - 0x2c, 0x9f, 0x96, 0x70, 0x2b, 0xc7, 0x0e, 0x0e, 0x33, 0x1b, 0x42, 0xd5, 0x25, 0x12, 0xda, 0x84, - 0x8c, 0x13, 0xb9, 0x53, 0x7e, 0x5c, 0x92, 0xf9, 0xca, 0x28, 0x1b, 0x63, 0x9e, 0x17, 0xcf, 0x3e, - 0x71, 0x08, 0xe1, 0x41, 0x3d, 0xda, 0xf0, 0xa8, 0xe3, 0xd2, 0x96, 0xb5, 0x4b, 0xdc, 0xd6, 0x2e, - 0xcf, 0x4f, 0x2c, 0x1a, 0x4b, 0x49, 0x33, 0x1b, 0xce, 0xdf, 0x92, 0xd3, 0x68, 0x13, 0x66, 0x22, - 0x51, 0x19, 0x21, 0x93, 0xc7, 0x8d, 0x90, 0xe9, 0x10, 0x40, 0x88, 0xa0, 0x77, 0x01, 0xa2, 0x18, - 0xcc, 0x83, 0x44, 0x2b, 0x1e, 0x1d, 0xcd, 0x71, 0x63, 0x62, 0x00, 0x88, 0xc2, 0xa9, 0x8e, 0x4b, - 0x2d, 0x46, 0xda, 0x4d, 0x4b, 0x33, 0x27, 0x70, 0x33, 0x92, 0xfe, 0x37, 0x8e, 0x71, 0x9a, 0x9f, - 0x3e, 0xb8, 0x9a, 0x55, 0xa3, 0xab, 0xcc, 0xd9, 0x5b, 0x7c, 0xad, 0xf4, 0xed, 0xef, 0x98, 0xb3, - 0x1d, 0x97, 0xd6, 0x49, 0xbb, 0x59, 0x09, 0x81, 0xd1, 0xeb, 0x70, 0x3e, 0x22, 0xc4, 0xa3, 0xd6, - 0xae, 0xd7, 0x76, 0x2c, 0x9f, 0x34, 0x2d, 0xdb, 0xeb, 0x51, 0x9e, 0x9f, 0x92, 0x34, 0x9e, 0x0b, - 0x45, 0x36, 0xe8, 0x2d, 0xaf, 0xed, 0x98, 0xa4, 0xb9, 0x26, 0x96, 0xd1, 0x2b, 0x10, 0xb1, 0x61, - 0xb9, 0x0e, 0xcb, 0x4f, 0x2f, 0x26, 0x97, 0x52, 0xe6, 0x54, 0x38, 0x59, 0x73, 0xd8, 0xea, 0xc4, - 0xfb, 0xf7, 0x17, 0xc6, 0x3e, 0xbf, 0xbf, 0x30, 0x56, 0xbc, 0x09, 0x53, 0x3b, 0xb8, 0xad, 0x43, - 0x8b, 0x30, 0x74, 0x1d, 0x26, 0x71, 0x30, 0xc8, 0x1b, 0x8b, 0xc9, 0x67, 0x86, 0x66, 0x24, 0x5a, - 0xfc, 0x9d, 0x01, 0xe9, 0xca, 0xce, 0x26, 0x76, 0x7d, 0x54, 0x85, 0xd9, 0xc8, 0x57, 0x9f, 0x37, - 0xca, 0x23, 0xf7, 0x0e, 0xc2, 0x7c, 0x1d, 0x66, 0xf7, 0x83, 0xc4, 0x11, 0xc2, 0xa8, 0x52, 0x73, - 0xf1, 0xd1, 0x83, 0xab, 0x17, 0x34, 0x4c, 0x98, 0x5c, 0x0e, 0xe0, 0xed, 0x1f, 0x98, 0x8f, 0xd9, - 0xfc, 0x16, 0x8c, 0xab, 0xad, 0x32, 0xf4, 0x5d, 0x78, 0xa9, 0x2b, 0x7e, 0x48, 0x53, 0x33, 0xd7, - 0xe6, 0x47, 0xfa, 0xbc, 0x94, 0x8f, 0x7b, 0x88, 0xd2, 0x2b, 0xfe, 0x22, 0x01, 0x50, 0xd9, 0xd9, - 0xd9, 0xf2, 0xdd, 0x6e, 0x9b, 0xf0, 0x2f, 0xcb, 0xf6, 0x6d, 0x38, 0x13, 0xd9, 0xce, 0x7c, 0xfb, - 0xf8, 0xf6, 0x9f, 0x0a, 0xf5, 0xeb, 0xbe, 0x7d, 0x28, 0xac, 0xc3, 0x78, 0x08, 0x9b, 0x3c, 0x3e, - 0x6c, 0x85, 0xf1, 0x61, 0x66, 0x7f, 0x00, 0x99, 0x88, 0x0c, 0x86, 0x6a, 0x30, 0xc1, 0xf5, 0x6f, - 0x4d, 0x70, 0x71, 0x34, 0xc1, 0x81, 0x5a, 0x9c, 0xe4, 0x50, 0xbd, 0xf8, 0x6f, 0x03, 0x20, 0x16, - 0x23, 0x5f, 0x4d, 0x1f, 0x43, 0x35, 0x48, 0xeb, 0xe4, 0x9c, 0x3c, 0x69, 0x72, 0xd6, 0x00, 0x31, - 0x52, 0x7f, 0x99, 0x80, 0x53, 0xdb, 0x41, 0xf4, 0x7e, 0xf5, 0x39, 0xd8, 0x86, 0x71, 0x42, 0xb9, - 0xef, 0x4a, 0x12, 0xc4, 0x99, 0xbf, 0x36, 0xea, 0xcc, 0x0f, 0x31, 0xaa, 0x4a, 0xb9, 0xdf, 0x8f, - 0x7b, 0x40, 0x80, 0x15, 0xe3, 0xe3, 0xd7, 0x49, 0xc8, 0x8f, 0x52, 0x45, 0xaf, 0x42, 0xd6, 0xf6, - 0x89, 0x9c, 0x08, 0xea, 0x8e, 0x21, 0x13, 0xe6, 0x4c, 0x30, 0xad, 0xcb, 0x8e, 0x09, 0xe2, 0xa2, - 0x26, 0x9c, 0x4b, 0x88, 0x9e, 0xec, 0x66, 0x36, 0x13, 0x21, 0xc8, 0xc2, 0xb3, 0x05, 0x59, 0x97, - 0xba, 0xdc, 0xc5, 0x6d, 0xab, 0x81, 0xdb, 0x98, 0xda, 0xc1, 0x0d, 0xf6, 0x58, 0x35, 0x7f, 0x46, - 0x63, 0x94, 0x15, 0x04, 0xaa, 0xc2, 0x78, 0x80, 0x96, 0x3a, 0x3e, 0x5a, 0xa0, 0x8b, 0x2e, 0xc2, - 0x54, 0xbc, 0x30, 0xc8, 0xdb, 0x48, 0xca, 0xcc, 0xc4, 0xea, 0xc2, 0x51, 0x95, 0x27, 0xfd, 0xcc, - 0xca, 0xa3, 0x2f, 0x7c, 0xbf, 0x49, 0xc2, 0xac, 0x49, 0x9c, 0xff, 0xfd, 0x63, 0xd9, 0x04, 0x50, - 0xa1, 0x2a, 0x32, 0xa9, 0x3e, 0x99, 0x13, 0xc4, 0xfb, 0xa4, 0x02, 0xa9, 0x30, 0xfe, 0xdf, 0x3a, - 0xa1, 0xbf, 0x26, 0x60, 0x2a, 0x7e, 0x42, 0xff, 0x97, 0x45, 0x0b, 0xad, 0x47, 0x69, 0x2a, 0x25, - 0xd3, 0xd4, 0xe5, 0x51, 0x69, 0x6a, 0xc8, 0x9b, 0x8f, 0xc8, 0x4f, 0x5f, 0x24, 0x21, 0xbd, 0x89, - 0x7d, 0xdc, 0x61, 0x68, 0x63, 0xe8, 0x6e, 0x1b, 0x74, 0x05, 0x0e, 0x3a, 0x73, 0x45, 0x77, 0x41, - 0x94, 0x2f, 0x7f, 0x38, 0xea, 0x6a, 0xfb, 0x35, 0x98, 0x11, 0x6f, 0xe4, 0xd0, 0x20, 0x45, 0xee, - 0xb4, 0x7c, 0xea, 0x86, 0xd6, 0x33, 0xb4, 0x00, 0x19, 0x21, 0x16, 0xe5, 0x61, 0x21, 0x03, 0x1d, - 0x7c, 0xa7, 0xaa, 0x66, 0xd0, 0x0a, 0xa0, 0xdd, 0xb0, 0x71, 0x61, 0x45, 0x44, 0x18, 0x4b, 0xd3, - 0xe5, 0x44, 0xde, 0x30, 0x67, 0xa3, 0xd5, 0x40, 0xe5, 0x02, 0x80, 0xd8, 0x89, 0xe5, 0x10, 0xea, - 0x75, 0xf4, 0x63, 0x6f, 0x52, 0xcc, 0x54, 0xc4, 0x04, 0xfa, 0xb9, 0xa1, 0xae, 0xc9, 0x07, 0x5e, - 0xd3, 0xfa, 0x95, 0xb2, 0xf5, 0x1c, 0x81, 0xf1, 0xaf, 0xc7, 0x0b, 0x85, 0x3e, 0xee, 0xb4, 0x57, - 0x8b, 0x87, 0xe0, 0x14, 0x0f, 0x7b, 0xe0, 0x8b, 0xcb, 0xf3, 0xe0, 0x6b, 0x1c, 0xd5, 0x20, 0xb7, - 0x47, 0xfa, 0x96, 0xef, 0x71, 0x95, 0x6c, 0x9a, 0x84, 0xe8, 0xf7, 0xcc, 0x5c, 0x70, 0xbe, 0x0d, - 0xcc, 0x48, 0xec, 0xfa, 0xef, 0xd2, 0x72, 0x4a, 0xec, 0xce, 0x9c, 0xd9, 0x23, 0x7d, 0x53, 0xeb, - 0xdd, 0x24, 0x64, 0xf5, 0x92, 0x88, 0x96, 0xbb, 0x9f, 0x7d, 0x7c, 0xe5, 0x7c, 0x74, 0x69, 0x5f, - 0xbe, 0x13, 0xf6, 0xc9, 0xd4, 0x11, 0x8b, 0x8b, 0x2f, 0x8a, 0x8a, 0x90, 0x49, 0x58, 0x57, 0xbc, - 0x29, 0xc5, 0x1b, 0x24, 0xf6, 0x56, 0x30, 0x9e, 0xfd, 0x06, 0x89, 0xf4, 0x07, 0xde, 0x20, 0xb1, - 0x10, 0x7d, 0x23, 0xaa, 0x01, 0x89, 0xa3, 0xac, 0x89, 0x7b, 0xa7, 0x56, 0x92, 0x91, 0x3f, 0x56, - 0xfc, 0xb3, 0x01, 0x73, 0x43, 0xde, 0x1c, 0x6e, 0xd9, 0x06, 0xe4, 0xc7, 0x16, 0xa5, 0x57, 0xf4, - 0xf5, 0xd6, 0x4f, 0x16, 0x1c, 0xb3, 0xfe, 0x50, 0x21, 0xf8, 0x72, 0x8a, 0x99, 0xce, 0x64, 0x7f, - 0x34, 0xe0, 0x74, 0x7c, 0x03, 0xa1, 0x29, 0x75, 0x98, 0x8a, 0x7f, 0x5a, 0x1b, 0x71, 0xe9, 0x79, - 0x8c, 0x88, 0xef, 0x7f, 0x00, 0x04, 0xed, 0x44, 0x19, 0x43, 0x75, 0xe7, 0x56, 0x9e, 0x9b, 0x94, - 0x60, 0x63, 0x87, 0x66, 0x0e, 0x75, 0x36, 0x5f, 0x18, 0x90, 0xda, 0xf4, 0xbc, 0x36, 0xfa, 0x19, - 0xcc, 0x52, 0x8f, 0x5b, 0x22, 0xb2, 0x88, 0x63, 0xe9, 0xd6, 0x81, 0xca, 0xc6, 0xd5, 0x67, 0x72, - 0xf5, 0x8f, 0xc7, 0x0b, 0xc3, 0x9a, 0x83, 0x04, 0xea, 0x0e, 0x15, 0xf5, 0x78, 0x59, 0x0a, 0x6d, - 0xa9, 0xee, 0x42, 0x13, 0xa6, 0x07, 0x3f, 0xa7, 0x32, 0xf6, 0x8d, 0xa3, 0x3e, 0x37, 0x7d, 0xe4, - 0xa7, 0xa6, 0x1a, 0xb1, 0xef, 0xac, 0x4e, 0x88, 0x53, 0xfb, 0xa7, 0x38, 0xb9, 0xf7, 0x20, 0x17, - 0xa6, 0xab, 0x6d, 0xd9, 0xde, 0x62, 0xe8, 0x26, 0x8c, 0xab, 0x4e, 0x57, 0xf0, 0x58, 0xb8, 0x18, - 0xf5, 0x4e, 0x71, 0xc3, 0x76, 0x4b, 0xfb, 0xb1, 0xbe, 0xa7, 0x52, 0x1a, 0xe0, 0x53, 0x2b, 0xcb, - 0xf6, 0xe7, 0xc3, 0x04, 0xcc, 0xad, 0x79, 0x94, 0xe9, 0x46, 0x8f, 0x8e, 0x6a, 0xd5, 0xab, 0xed, - 0xa3, 0xcb, 0x23, 0xda, 0x50, 0x53, 0xc3, 0xcd, 0xa6, 0x1d, 0xc8, 0x8a, 0x12, 0x6b, 0x7b, 0xf4, - 0x05, 0x7b, 0x4d, 0xd3, 0x5e, 0xdb, 0xd1, 0x3b, 0xda, 0x23, 0x7d, 0x81, 0x4b, 0xc9, 0xed, 0x01, - 0xdc, 0xe4, 0xc9, 0x70, 0x29, 0xb9, 0x1d, 0xc3, 0x3d, 0x0b, 0x69, 0x7d, 0xbf, 0x4a, 0xc9, 0xdb, - 0x83, 0x1e, 0xa1, 0xeb, 0x90, 0x14, 0xa9, 0xf0, 0xa5, 0x63, 0x24, 0x0f, 0xa1, 0x10, 0x2b, 0x6b, - 0x75, 0x98, 0xd3, 0x9d, 0x02, 0xb6, 0xd1, 0x94, 0x8c, 0x12, 0x69, 0xd0, 0xdb, 0xa4, 0x7f, 0x48, - 0xdb, 0x60, 0xea, 0xb9, 0xda, 0x06, 0x57, 0x7e, 0x6f, 0x00, 0x44, 0x3d, 0x33, 0xf4, 0x4d, 0x38, - 0x57, 0xde, 0x58, 0xaf, 0x58, 0xf5, 0xad, 0x1b, 0x5b, 0xdb, 0x75, 0x6b, 0x7b, 0xbd, 0xbe, 0x59, - 0x5d, 0xab, 0xdd, 0xac, 0x55, 0x2b, 0xb9, 0xb1, 0x42, 0xf6, 0xee, 0xbd, 0xc5, 0xcc, 0x36, 0x65, - 0x5d, 0x62, 0xbb, 0x4d, 0x97, 0x38, 0xe8, 0xeb, 0x70, 0x7a, 0x50, 0x5a, 0x8c, 0xaa, 0x95, 0x9c, - 0x51, 0x98, 0xba, 0x7b, 0x6f, 0x71, 0x42, 0xbd, 0x11, 0x88, 0x83, 0x96, 0xe0, 0xcc, 0xb0, 0x5c, - 0x6d, 0xfd, 0xcd, 0x5c, 0xa2, 0x30, 0x7d, 0xf7, 0xde, 0xe2, 0x64, 0xf8, 0x98, 0x40, 0x45, 0x40, - 0x71, 0x49, 0x8d, 0x97, 0x2c, 0xc0, 0xdd, 0x7b, 0x8b, 0x69, 0x15, 0x32, 0x85, 0xd4, 0xfb, 0xbf, - 0x9d, 0x1f, 0xbb, 0xf2, 0x13, 0x80, 0x1a, 0x6d, 0xfa, 0xd8, 0x96, 0xa9, 0xa1, 0x00, 0x67, 0x6b, - 0xeb, 0x37, 0xcd, 0x1b, 0x6b, 0x5b, 0xb5, 0x8d, 0xf5, 0xc1, 0x6d, 0x1f, 0x58, 0xab, 0x6c, 0x6c, - 0x97, 0xdf, 0xa9, 0x5a, 0xf5, 0xda, 0x9b, 0xeb, 0x39, 0x03, 0x9d, 0x83, 0x53, 0x03, 0x6b, 0xdf, - 0x5f, 0xdf, 0xaa, 0xbd, 0x5b, 0xcd, 0x25, 0xca, 0xd7, 0x3f, 0x79, 0x32, 0x6f, 0x3c, 0x7c, 0x32, - 0x6f, 0xfc, 0xfd, 0xc9, 0xbc, 0xf1, 0xc1, 0xd3, 0xf9, 0xb1, 0x87, 0x4f, 0xe7, 0xc7, 0xfe, 0xf2, - 0x74, 0x7e, 0xec, 0x47, 0x2f, 0x0f, 0x04, 0x63, 0x54, 0x8e, 0xe4, 0x7f, 0x17, 0x1a, 0x69, 0xe9, - 0x35, 0xdf, 0xfa, 0x4f, 0x00, 0x00, 0x00, 0xff, 0xff, 0xf4, 0xd1, 0x83, 0x1f, 0xd5, 0x19, 0x00, - 0x00, + 0x19, 0xd6, 0x92, 0x34, 0x25, 0xfe, 0x14, 0x45, 0x6a, 0xfc, 0xa2, 0xe8, 0x58, 0x92, 0x19, 0x37, + 0x91, 0xdd, 0x98, 0x8c, 0xdc, 0xc2, 0x05, 0x84, 0x20, 0x85, 0x29, 0xca, 0x36, 0x93, 0x58, 0x52, + 0x97, 0xa2, 0xfa, 0x40, 0x9b, 0xc5, 0x70, 0x77, 0x48, 0x6d, 0x45, 0xee, 0xb2, 0x3b, 0x43, 0xd9, + 0xbc, 0xf7, 0x10, 0xb8, 0x28, 0x90, 0x53, 0x11, 0xa0, 0x30, 0x6a, 0xa0, 0x97, 0xf6, 0x96, 0x83, + 0xd1, 0x7b, 0x6f, 0x69, 0x81, 0x02, 0x86, 0x4f, 0x45, 0x80, 0xba, 0x85, 0x7d, 0x48, 0xd0, 0x5c, + 0xda, 0x9e, 0x7a, 0x2c, 0xe6, 0xb1, 0x0f, 0x8a, 0xa2, 0x65, 0xc9, 0x41, 0x11, 0xb4, 0x17, 0x62, + 0x67, 0xe6, 0xff, 0xbf, 0x99, 0xff, 0x3d, 0xf3, 0x13, 0x2e, 0x9a, 0x2e, 0xed, 0xba, 0xb4, 0x4c, + 0x19, 0xde, 0xb5, 0x9d, 0x76, 0x79, 0x6f, 0xb9, 0x49, 0x18, 0x5e, 0xf6, 0xc7, 0xa5, 0x9e, 0xe7, + 0x32, 0x17, 0x9d, 0x91, 0x54, 0x25, 0x7f, 0x56, 0x51, 0x15, 0x66, 0x71, 0xd7, 0x76, 0xdc, 0xb2, + 0xf8, 0x95, 0xa4, 0x85, 0x57, 0x4c, 0xb7, 0x4b, 0x58, 0xb3, 0xc5, 0xca, 0xb8, 0x69, 0xda, 0xe5, + 0xbd, 0xe5, 0x32, 0x1b, 0xf4, 0x08, 0x55, 0xab, 0xe7, 0x83, 0x55, 0x31, 0xbb, 0x7f, 0x79, 0x5e, + 0x9d, 0xa6, 0x89, 0x29, 0x09, 0x8e, 0x62, 0xba, 0xb6, 0xa3, 0xd6, 0xe7, 0xe4, 0xba, 0x21, 0x46, + 0x65, 0x75, 0x28, 0xb9, 0x74, 0xaa, 0xed, 0xb6, 0x5d, 0x39, 0xcf, 0xbf, 0x7c, 0x86, 0xb6, 0xeb, + 0xb6, 0x3b, 0xa4, 0x2c, 0x46, 0xcd, 0x7e, 0xab, 0x8c, 0x9d, 0x81, 0xbf, 0xd7, 0xfe, 0x25, 0xab, + 0xef, 0x61, 0x66, 0xbb, 0xfe, 0x5e, 0x0b, 0xfb, 0xd7, 0x99, 0xdd, 0x25, 0x94, 0xe1, 0x6e, 0x4f, + 0x12, 0x14, 0x3f, 0xd2, 0x60, 0xe6, 0x96, 0x4d, 0x99, 0xeb, 0xd9, 0x26, 0xee, 0xd4, 0x9c, 0x96, + 0x8b, 0xde, 0x82, 0xe4, 0x0e, 0xc1, 0x16, 0xf1, 0xf2, 0xda, 0xa2, 0xb6, 0x94, 0xbe, 0x3a, 0x57, + 0xf2, 0xe5, 0x2d, 0x49, 0x31, 0xf7, 0x96, 0x4b, 0xb7, 0x04, 0x41, 0x25, 0xf5, 0xc9, 0x93, 0x85, + 0x89, 0xdf, 0x7c, 0xf6, 0xf1, 0x65, 0x4d, 0x57, 0x3c, 0xa8, 0x0a, 0xc9, 0x3d, 0xdc, 0xa1, 0x84, + 0xe5, 0x63, 0x8b, 0xf1, 0xa5, 0xf4, 0xd5, 0x0b, 0xa5, 0x83, 0xd5, 0x5e, 0xda, 0xc6, 0x1d, 0xdb, + 0xc2, 0xcc, 0x1d, 0x46, 0x91, 0xbc, 0x2b, 0xb1, 0xbc, 0x56, 0xfc, 0x45, 0x0c, 0xb2, 0xab, 0x6e, + 0xb7, 0x6b, 0x53, 0x6a, 0xbb, 0x8e, 0x8e, 0x19, 0xa1, 0xe8, 0x1d, 0x48, 0x78, 0x98, 0x11, 0x71, + 0xb2, 0x54, 0xe5, 0x1a, 0x67, 0xfc, 0xf4, 0xc9, 0xc2, 0x39, 0xb9, 0x05, 0xb5, 0x76, 0x4b, 0xb6, + 0x5b, 0xee, 0x62, 0xb6, 0x53, 0x7a, 0x8f, 0xb4, 0xb1, 0x39, 0xa8, 0x12, 0xf3, 0xf1, 0xc3, 0x2b, + 0xa0, 0x4e, 0x50, 0x25, 0xa6, 0xdc, 0x45, 0x60, 0xa0, 0xef, 0xc0, 0x54, 0x17, 0xdf, 0x35, 0x04, + 0x5e, 0xec, 0xa5, 0xf0, 0x26, 0xbb, 0xf8, 0x2e, 0x3f, 0x1f, 0x7a, 0x1f, 0xb2, 0x1c, 0xd2, 0xdc, + 0xc1, 0x4e, 0x9b, 0x48, 0xe4, 0xf8, 0x4b, 0x21, 0x67, 0xba, 0xf8, 0xee, 0xaa, 0x40, 0xe3, 0xf8, + 0x2b, 0x89, 0xcf, 0x1f, 0x2c, 0x68, 0xc5, 0xdf, 0x6b, 0x00, 0xa1, 0x62, 0x10, 0x86, 0x9c, 0x19, + 0x8c, 0xc4, 0xa6, 0x54, 0x59, 0xee, 0xf5, 0x71, 0xba, 0xdf, 0xa7, 0xd6, 0x4a, 0x86, 0x1f, 0xef, + 0xd1, 0x93, 0x05, 0x4d, 0xee, 0x9a, 0x35, 0x47, 0xd4, 0x9e, 0xee, 0xf7, 0x2c, 0xcc, 0x88, 0xc1, + 0xfd, 0x47, 0x68, 0x2b, 0x7d, 0xb5, 0x50, 0x92, 0xce, 0x55, 0xf2, 0x9d, 0xab, 0xb4, 0xe5, 0x3b, + 0x97, 0x04, 0xfc, 0xf0, 0xaf, 0x3e, 0x20, 0x48, 0x6e, 0xbe, 0xae, 0x64, 0xf8, 0xa7, 0x06, 0xe9, + 0x2a, 0xa1, 0xa6, 0x67, 0xf7, 0xb8, 0xbb, 0xa2, 0x3c, 0x4c, 0x76, 0x5d, 0xc7, 0xde, 0x55, 0x5e, + 0x97, 0xd2, 0xfd, 0x21, 0x2a, 0xc0, 0x94, 0x6d, 0x11, 0x87, 0xd9, 0x6c, 0x20, 0xcd, 0xa4, 0x07, + 0x63, 0xce, 0x75, 0x87, 0x34, 0xa9, 0xed, 0xeb, 0x59, 0xf7, 0x87, 0xe8, 0x12, 0xe4, 0x28, 0x31, + 0xfb, 0x9e, 0xcd, 0x06, 0x86, 0xe9, 0x3a, 0x0c, 0x9b, 0x2c, 0x9f, 0x10, 0x24, 0x59, 0x7f, 0x7e, + 0x55, 0x4e, 0x73, 0x10, 0x8b, 0x30, 0x6c, 0x77, 0x68, 0xfe, 0x84, 0x04, 0x51, 0x43, 0x74, 0x13, + 0xa6, 0xba, 0x84, 0x61, 0x0b, 0x33, 0x9c, 0x4f, 0x0a, 0x99, 0x17, 0xc7, 0x69, 0xf4, 0xb6, 0xa2, + 0x8b, 0x3a, 0x73, 0xc0, 0xac, 0x64, 0x6e, 0xc1, 0x94, 0x4f, 0x86, 0x5e, 0x83, 0x6c, 0xcf, 0x73, + 0x5b, 0x76, 0x87, 0x18, 0x3d, 0xdb, 0x34, 0xfa, 0x9e, 0xad, 0xe4, 0xce, 0xa8, 0xe9, 0x4d, 0xdb, + 0x6c, 0x78, 0x36, 0x7a, 0x03, 0x10, 0x75, 0x4d, 0x1b, 0x77, 0x8c, 0x1d, 0xec, 0x58, 0x1d, 0xc2, + 0x29, 0xa9, 0x08, 0xad, 0x94, 0x9e, 0x93, 0x2b, 0xb7, 0xc4, 0x42, 0xc3, 0xb3, 0xa9, 0xda, 0xe7, + 0xfe, 0x24, 0xa4, 0x82, 0xe8, 0x42, 0xab, 0x90, 0x73, 0x7b, 0xc4, 0xe3, 0xdf, 0x06, 0xb6, 0x2c, + 0x8f, 0x50, 0xaa, 0xc2, 0x27, 0xff, 0xf8, 0xe1, 0x95, 0x53, 0x4a, 0x9e, 0xeb, 0x72, 0xa5, 0xce, + 0x3c, 0xdb, 0x69, 0xeb, 0x59, 0x9f, 0x43, 0x4d, 0xa3, 0xef, 0x73, 0x1f, 0x73, 0x28, 0x71, 0x68, + 0x9f, 0x1a, 0xbd, 0x7e, 0x73, 0x97, 0x0c, 0x94, 0x17, 0x9c, 0x1a, 0xf1, 0x82, 0xeb, 0xce, 0xa0, + 0x92, 0xff, 0x63, 0x08, 0x6d, 0x7a, 0x83, 0x1e, 0x73, 0x4b, 0x9b, 0xfd, 0xe6, 0xbb, 0x64, 0xc0, + 0x7d, 0x4b, 0xe1, 0x6c, 0x0a, 0x18, 0x74, 0x06, 0x92, 0x3f, 0xc6, 0x76, 0x87, 0x58, 0xc2, 0x84, + 0x53, 0xba, 0x1a, 0xa1, 0x15, 0x48, 0x52, 0x86, 0x59, 0x9f, 0x0a, 0xbb, 0xcd, 0x5c, 0x2d, 0x8e, + 0x53, 0x7d, 0xc5, 0x75, 0xac, 0xba, 0xa0, 0xd4, 0x15, 0x07, 0x5a, 0x85, 0x24, 0x73, 0x77, 0x89, + 0xa3, 0x2c, 0x5a, 0xf9, 0xba, 0x0a, 0xbf, 0xd3, 0xa3, 0xe1, 0x57, 0x73, 0x58, 0x24, 0xf0, 0x6a, + 0x0e, 0xd3, 0x15, 0x2b, 0xfa, 0x21, 0xe4, 0x2c, 0xd2, 0x21, 0x6d, 0xa1, 0x39, 0xba, 0x83, 0x3d, + 0x42, 0x85, 0x17, 0xa4, 0x2a, 0xcb, 0x47, 0x8e, 0x66, 0x3d, 0x1b, 0x40, 0xd5, 0x05, 0x12, 0xda, + 0x84, 0xb4, 0x15, 0xfa, 0x7f, 0x7e, 0x52, 0x28, 0xf3, 0xd5, 0x71, 0x32, 0x46, 0x42, 0x25, 0xea, + 0x61, 0x51, 0x08, 0xee, 0xf2, 0x7d, 0xa7, 0xe9, 0x3a, 0x96, 0xed, 0xb4, 0x8d, 0x1d, 0x62, 0xb7, + 0x77, 0x58, 0x7e, 0x6a, 0x51, 0x5b, 0x8a, 0xeb, 0xd9, 0x60, 0xfe, 0x96, 0x98, 0x46, 0x9b, 0x30, + 0x13, 0x92, 0x8a, 0x90, 0x4e, 0x1d, 0x35, 0xa4, 0x33, 0x01, 0x00, 0x27, 0x41, 0xb7, 0x01, 0xc2, + 0xa4, 0x91, 0x07, 0x81, 0x56, 0x3c, 0x3c, 0xfd, 0x44, 0x85, 0x89, 0x00, 0x20, 0x07, 0x4e, 0x76, + 0x6d, 0xc7, 0xa0, 0xa4, 0xd3, 0x32, 0x94, 0xe6, 0x38, 0x6e, 0x5a, 0xa8, 0xff, 0xed, 0x23, 0x58, + 0xf3, 0xd3, 0x87, 0x57, 0xb2, 0x72, 0x74, 0x85, 0x5a, 0xbb, 0x8b, 0x6f, 0x96, 0xbe, 0xf9, 0x2d, + 0x7d, 0xb6, 0x6b, 0x3b, 0x75, 0xd2, 0x69, 0x55, 0x03, 0x60, 0xf4, 0x16, 0x9c, 0x0b, 0x15, 0xe2, + 0x3a, 0xc6, 0x8e, 0xdb, 0xb1, 0x0c, 0x8f, 0xb4, 0x0c, 0xd3, 0xed, 0x3b, 0x2c, 0x3f, 0x2d, 0xd4, + 0x78, 0x36, 0x20, 0xd9, 0x70, 0x6e, 0xb9, 0x1d, 0x4b, 0x27, 0xad, 0x55, 0xbe, 0x8c, 0x5e, 0x85, + 0x50, 0x1b, 0x86, 0x6d, 0xd1, 0x7c, 0x66, 0x31, 0xbe, 0x94, 0xd0, 0xa7, 0x83, 0xc9, 0x9a, 0x45, + 0x57, 0xa6, 0x3e, 0x78, 0xb0, 0x30, 0xf1, 0xf9, 0x83, 0x85, 0x89, 0xe2, 0x0d, 0x98, 0xde, 0xc6, + 0x1d, 0x15, 0x5a, 0x84, 0xa2, 0x6b, 0x90, 0xc2, 0xfe, 0x20, 0xaf, 0xf1, 0xd0, 0x7e, 0x4e, 0x68, + 0x86, 0xa4, 0xc5, 0xdf, 0x6a, 0x90, 0xac, 0x6e, 0x6f, 0x62, 0xdb, 0x43, 0x6b, 0x30, 0x1b, 0xfa, + 0xea, 0x8b, 0x46, 0x79, 0xe8, 0xde, 0x7e, 0x98, 0xaf, 0xc3, 0xec, 0x9e, 0x9f, 0x38, 0x02, 0x18, + 0x59, 0x1b, 0x2f, 0x3c, 0x7e, 0x78, 0xe5, 0xbc, 0x82, 0x09, 0x92, 0xcb, 0x3e, 0xbc, 0xbd, 0x7d, + 0xf3, 0x11, 0x99, 0xdf, 0x81, 0x49, 0x79, 0x54, 0x8a, 0xbe, 0x0d, 0x27, 0x7a, 0xfc, 0x43, 0x88, + 0x9a, 0xbe, 0x3a, 0x3f, 0xd6, 0xe7, 0x05, 0x7d, 0xd4, 0x43, 0x24, 0x5f, 0xf1, 0x67, 0x31, 0x80, + 0xea, 0xf6, 0xf6, 0x96, 0x67, 0xf7, 0x3a, 0x84, 0x7d, 0x59, 0xb2, 0x37, 0xe0, 0x74, 0x28, 0x3b, + 0xf5, 0xcc, 0xa3, 0xcb, 0x7f, 0x32, 0xe0, 0xaf, 0x7b, 0xe6, 0x81, 0xb0, 0x16, 0x65, 0x01, 0x6c, + 0xfc, 0xe8, 0xb0, 0x55, 0xca, 0x46, 0x35, 0xfb, 0x3d, 0x48, 0x87, 0xca, 0xa0, 0xa8, 0x06, 0x53, + 0x4c, 0x7d, 0x2b, 0x05, 0x17, 0xc7, 0x2b, 0xd8, 0x67, 0x1b, 0xaa, 0x5a, 0x3e, 0x7b, 0xf1, 0xdf, + 0x1a, 0x40, 0x24, 0x46, 0xbe, 0x9a, 0x3e, 0x86, 0x6a, 0x90, 0x54, 0xc9, 0x39, 0x7e, 0xdc, 0xe4, + 0xac, 0x00, 0x22, 0x4a, 0xfd, 0x79, 0x0c, 0x4e, 0x36, 0xfc, 0xe8, 0xfd, 0xea, 0xeb, 0xa0, 0x01, + 0x93, 0xc4, 0x61, 0x9e, 0x2d, 0x94, 0xc0, 0x6d, 0xfe, 0xe6, 0x38, 0x9b, 0x1f, 0x20, 0xd4, 0x9a, + 0xc3, 0xbc, 0x41, 0xd4, 0x03, 0x7c, 0xac, 0x88, 0x3e, 0x7e, 0x19, 0x87, 0xfc, 0x38, 0x56, 0xf4, + 0x3a, 0x64, 0x4d, 0x8f, 0x88, 0x09, 0xbf, 0xee, 0x68, 0x22, 0x61, 0xce, 0xf8, 0xd3, 0xaa, 0xec, + 0xe8, 0xc0, 0x6f, 0x96, 0xdc, 0xb9, 0x38, 0xe9, 0xf1, 0xae, 0x92, 0x33, 0x21, 0x82, 0x28, 0x3c, + 0x5b, 0x90, 0xb5, 0x1d, 0x9b, 0xf1, 0x1b, 0x52, 0x13, 0x77, 0xb0, 0x63, 0xfa, 0x57, 0xee, 0x23, + 0xd5, 0xfc, 0x19, 0x85, 0x51, 0x91, 0x10, 0x68, 0x0d, 0x26, 0x7d, 0xb4, 0xc4, 0xd1, 0xd1, 0x7c, + 0x5e, 0x74, 0x01, 0xa6, 0xa3, 0x85, 0x41, 0xdc, 0x46, 0x12, 0x7a, 0x3a, 0x52, 0x17, 0x0e, 0xab, + 0x3c, 0xc9, 0xe7, 0x56, 0x1e, 0x75, 0xe1, 0xfb, 0x55, 0x1c, 0x66, 0x75, 0x62, 0xfd, 0xef, 0x9b, + 0x65, 0x13, 0x40, 0x86, 0x2a, 0xcf, 0xa4, 0xca, 0x32, 0xc7, 0x88, 0xf7, 0x94, 0x04, 0xa9, 0x52, + 0xf6, 0xdf, 0xb2, 0xd0, 0x5f, 0x62, 0x30, 0x1d, 0xb5, 0xd0, 0xff, 0x65, 0xd1, 0x42, 0xeb, 0x61, + 0x9a, 0x4a, 0x88, 0x34, 0x75, 0x69, 0x5c, 0x9a, 0x1a, 0xf1, 0xe6, 0x43, 0xf2, 0xd3, 0x17, 0x71, + 0x48, 0x6e, 0x62, 0x0f, 0x77, 0x29, 0xda, 0x18, 0xb9, 0xdb, 0xfa, 0x6d, 0x8c, 0xfd, 0xce, 0x5c, + 0x55, 0xbd, 0x12, 0xe9, 0xcb, 0x1f, 0x8d, 0xbb, 0xda, 0x7e, 0x0d, 0x66, 0xf8, 0xa3, 0x3e, 0x10, + 0x48, 0x2a, 0x37, 0x23, 0xde, 0xe6, 0x81, 0xf4, 0x14, 0x2d, 0x40, 0x9a, 0x93, 0x85, 0x79, 0x98, + 0xd3, 0x40, 0x17, 0xdf, 0x5d, 0x93, 0x33, 0x68, 0x19, 0xd0, 0x4e, 0xd0, 0x69, 0x31, 0x42, 0x45, + 0x68, 0x4b, 0x99, 0x4a, 0x2c, 0xaf, 0xe9, 0xb3, 0xe1, 0xaa, 0xcf, 0x72, 0x1e, 0x80, 0x9f, 0xc4, + 0xb0, 0x88, 0xe3, 0x76, 0xd5, 0xeb, 0x34, 0xc5, 0x67, 0xaa, 0x7c, 0x02, 0xfd, 0x54, 0x93, 0xd7, + 0xe4, 0x7d, 0xcf, 0x7f, 0xf5, 0x4a, 0xd9, 0x7a, 0x81, 0xc0, 0xf8, 0xd7, 0x93, 0x85, 0xc2, 0x00, + 0x77, 0x3b, 0x2b, 0xc5, 0x03, 0x70, 0x8a, 0x07, 0x75, 0x24, 0xf8, 0xe5, 0x79, 0xb8, 0x7d, 0x80, + 0x6a, 0x90, 0xdb, 0x25, 0x03, 0xc3, 0x73, 0x99, 0x4c, 0x36, 0x2d, 0x42, 0xd4, 0x7b, 0x66, 0xce, + 0xb7, 0x6f, 0x13, 0x53, 0x12, 0xb9, 0xfe, 0xdb, 0x4e, 0x25, 0xc1, 0x4f, 0xa7, 0xcf, 0xec, 0x92, + 0x81, 0xae, 0xf8, 0x6e, 0x10, 0xb2, 0x72, 0x91, 0x47, 0xcb, 0xbd, 0xcf, 0x3e, 0xbe, 0x7c, 0x2e, + 0xbc, 0xb4, 0x97, 0xef, 0x06, 0x8d, 0x3d, 0x69, 0x62, 0x7e, 0xf1, 0x45, 0x61, 0x11, 0xd2, 0x09, + 0xed, 0xf1, 0x37, 0x25, 0x7f, 0x83, 0x44, 0xde, 0x0a, 0xda, 0xf3, 0xdf, 0x20, 0x21, 0xff, 0xd0, + 0x1b, 0x24, 0x12, 0xa2, 0x6f, 0x87, 0x35, 0x20, 0x76, 0x98, 0x34, 0x51, 0xef, 0x54, 0x4c, 0x22, + 0xf2, 0x27, 0x8a, 0x7f, 0xd2, 0x60, 0x6e, 0xc4, 0x9b, 0x83, 0x23, 0x9b, 0x80, 0xbc, 0xc8, 0xa2, + 0xf0, 0x8a, 0x81, 0x3a, 0xfa, 0xf1, 0x82, 0x63, 0xd6, 0x1b, 0x29, 0x04, 0x5f, 0x4e, 0x31, 0x53, + 0x99, 0xec, 0x0f, 0x1a, 0x9c, 0x8a, 0x1e, 0x20, 0x10, 0xa5, 0x0e, 0xd3, 0xd1, 0xad, 0x95, 0x10, + 0x17, 0x5f, 0x44, 0x88, 0xe8, 0xf9, 0x87, 0x40, 0xd0, 0x76, 0x98, 0x31, 0x64, 0x3b, 0x71, 0xf9, + 0x85, 0x95, 0xe2, 0x1f, 0xec, 0xc0, 0xcc, 0x21, 0x6d, 0xf3, 0x85, 0x06, 0x89, 0x4d, 0xd7, 0xed, + 0xa0, 0x9f, 0xc0, 0xac, 0xe3, 0x32, 0x83, 0x47, 0x16, 0xb1, 0x0c, 0xd5, 0x3a, 0x90, 0xd9, 0x78, + 0xed, 0xb9, 0xba, 0xfa, 0xfb, 0x93, 0x85, 0x51, 0xce, 0x61, 0x05, 0xaa, 0x96, 0x9a, 0xe3, 0xb2, + 0x8a, 0x20, 0xda, 0x92, 0xdd, 0x85, 0x16, 0x64, 0x86, 0xb7, 0x93, 0x19, 0xfb, 0xfa, 0x61, 0xdb, + 0x65, 0x0e, 0xdd, 0x6a, 0xba, 0x19, 0xd9, 0x67, 0x65, 0x8a, 0x5b, 0xed, 0x1f, 0xdc, 0x72, 0xef, + 0x43, 0x2e, 0x48, 0x57, 0x0d, 0xd1, 0x8f, 0xa3, 0xe8, 0x06, 0x4c, 0xca, 0xd6, 0x9c, 0xff, 0x58, + 0xb8, 0x10, 0x36, 0x7b, 0x71, 0xd3, 0xb4, 0x4b, 0x7b, 0x91, 0x46, 0xad, 0x64, 0x1a, 0xd2, 0xa7, + 0x62, 0x16, 0xfd, 0xda, 0x47, 0x31, 0x98, 0x5b, 0x75, 0x1d, 0xaa, 0x1a, 0x3d, 0x2a, 0xaa, 0x65, + 0x73, 0x79, 0x80, 0x2e, 0x8d, 0x69, 0x43, 0x4d, 0x8f, 0x36, 0x9b, 0xb6, 0x21, 0xcb, 0x4b, 0xac, + 0xe9, 0x3a, 0x2f, 0xd9, 0x6b, 0xca, 0xb8, 0x1d, 0x4b, 0x9d, 0x68, 0x97, 0x0c, 0x38, 0xae, 0x43, + 0xee, 0x0c, 0xe1, 0xc6, 0x8f, 0x87, 0xeb, 0x90, 0x3b, 0x11, 0xdc, 0x33, 0x90, 0x54, 0xf7, 0xab, + 0x84, 0xb8, 0x3d, 0xa8, 0x11, 0xba, 0x06, 0x71, 0x9e, 0x0a, 0x4f, 0x1c, 0x21, 0x79, 0x70, 0x86, + 0x48, 0x59, 0xab, 0xc3, 0x9c, 0xea, 0x14, 0xd0, 0x8d, 0x96, 0xd0, 0x28, 0x11, 0x02, 0xbd, 0x4b, + 0x06, 0x07, 0xb4, 0x0d, 0xa6, 0x5f, 0xa8, 0x6d, 0x70, 0xf9, 0x77, 0x1a, 0x40, 0xd8, 0x33, 0x43, + 0x6f, 0xc0, 0xd9, 0xca, 0xc6, 0x7a, 0xd5, 0xa8, 0x6f, 0x5d, 0xdf, 0x6a, 0xd4, 0x8d, 0xc6, 0x7a, + 0x7d, 0x73, 0x6d, 0xb5, 0x76, 0xa3, 0xb6, 0x56, 0xcd, 0x4d, 0x14, 0xb2, 0xf7, 0xee, 0x2f, 0xa6, + 0x1b, 0x0e, 0xed, 0x11, 0xd3, 0x6e, 0xd9, 0xc4, 0x42, 0xaf, 0xc1, 0xa9, 0x61, 0x6a, 0x3e, 0x5a, + 0xab, 0xe6, 0xb4, 0xc2, 0xf4, 0xbd, 0xfb, 0x8b, 0x53, 0xf2, 0x8d, 0x40, 0x2c, 0xb4, 0x04, 0xa7, + 0x47, 0xe9, 0x6a, 0xeb, 0x37, 0x73, 0xb1, 0x42, 0xe6, 0xde, 0xfd, 0xc5, 0x54, 0xf0, 0x98, 0x40, + 0x45, 0x40, 0x51, 0x4a, 0x85, 0x17, 0x2f, 0xc0, 0xbd, 0xfb, 0x8b, 0x49, 0x19, 0x32, 0x85, 0xc4, + 0x07, 0xbf, 0x9e, 0x9f, 0xb8, 0xfc, 0x23, 0x80, 0x9a, 0xd3, 0xf2, 0xb0, 0x29, 0x52, 0x43, 0x01, + 0xce, 0xd4, 0xd6, 0x6f, 0xe8, 0xd7, 0x57, 0xb7, 0x6a, 0x1b, 0xeb, 0xc3, 0xc7, 0xde, 0xb7, 0x56, + 0xdd, 0x68, 0x54, 0xde, 0x5b, 0x33, 0xea, 0xb5, 0x9b, 0xeb, 0x39, 0x0d, 0x9d, 0x85, 0x93, 0x43, + 0x6b, 0xdf, 0x5d, 0xdf, 0xaa, 0xdd, 0x5e, 0xcb, 0xc5, 0x2a, 0xd7, 0x3e, 0x79, 0x3a, 0xaf, 0x3d, + 0x7a, 0x3a, 0xaf, 0xfd, 0xed, 0xe9, 0xbc, 0xf6, 0xe1, 0xb3, 0xf9, 0x89, 0x47, 0xcf, 0xe6, 0x27, + 0xfe, 0xfc, 0x6c, 0x7e, 0xe2, 0x07, 0xaf, 0x0c, 0x05, 0x63, 0x58, 0x8e, 0xc4, 0xdf, 0x21, 0xcd, + 0xa4, 0xf0, 0x9a, 0x6f, 0xfc, 0x27, 0x00, 0x00, 0xff, 0xff, 0x85, 0x67, 0xcc, 0xc5, 0x86, 0x1a, + 0x00, 0x00, } func (this *Pool) Description() (desc *github_com_cosmos_gogoproto_protoc_gen_gogo_descriptor.FileDescriptorSet) { @@ -1523,743 +1593,750 @@ func (this *Pool) Description() (desc *github_com_cosmos_gogoproto_protoc_gen_go func StakingDescription() (desc *github_com_cosmos_gogoproto_protoc_gen_gogo_descriptor.FileDescriptorSet) { d := &github_com_cosmos_gogoproto_protoc_gen_gogo_descriptor.FileDescriptorSet{} var gzipped = []byte{ - // 11763 bytes of a gzipped FileDescriptorSet - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x7d, 0x7b, 0x90, 0x63, 0xd9, - 0x59, 0xdf, 0x5c, 0x49, 0xad, 0x96, 0x3e, 0x49, 0xad, 0xdb, 0xa7, 0x7b, 0x66, 0x34, 0x3d, 0xbb, - 0xd3, 0x3d, 0x77, 0x76, 0x77, 0x66, 0x67, 0x77, 0x7b, 0x76, 0x66, 0x67, 0x67, 0x77, 0xb5, 0x2f, - 0x24, 0xb5, 0x7a, 0x46, 0xb3, 0xfd, 0xf2, 0x95, 0xba, 0xbd, 0xbb, 0x3c, 0x2e, 0xb7, 0xaf, 0x4e, - 0x77, 0xdf, 0x1d, 0xe9, 0x5e, 0x59, 0xf7, 0x6a, 0xa6, 0x7b, 0x53, 0x95, 0x32, 0x01, 0x13, 0xb3, - 0x3c, 0x62, 0x02, 0x01, 0x63, 0x7b, 0x8c, 0x81, 0x80, 0x6d, 0x08, 0x04, 0x62, 0x43, 0x20, 0x54, - 0x1e, 0xa4, 0x12, 0x02, 0xa4, 0x42, 0x1c, 0xaa, 0x92, 0x50, 0x54, 0xb1, 0x01, 0x9b, 0x2a, 0x1c, - 0x6c, 0x08, 0x10, 0x9b, 0xa2, 0xe2, 0x4a, 0x2a, 0x75, 0x5e, 0xf7, 0x21, 0x5d, 0xb5, 0xd4, 0xb3, - 0xbb, 0xc6, 0x81, 0xfc, 0x33, 0xd3, 0xf7, 0x9c, 0xef, 0xfb, 0x9d, 0x73, 0xbe, 0xf3, 0x9d, 0xef, - 0x7c, 0xe7, 0x3b, 0x0f, 0xc1, 0xef, 0x2f, 0xc3, 0xc2, 0xae, 0x6d, 0xef, 0xb6, 0xf0, 0xa5, 0x4e, - 0xd7, 0x76, 0xed, 0xed, 0xde, 0xce, 0xa5, 0x26, 0x76, 0x8c, 0xae, 0xd9, 0x71, 0xed, 0xee, 0x22, - 0x4d, 0x43, 0x79, 0x46, 0xb1, 0x28, 0x28, 0x94, 0x55, 0x98, 0x5e, 0x36, 0x5b, 0x78, 0xc9, 0x23, - 0xac, 0x63, 0x17, 0x3d, 0x0d, 0x89, 0x1d, 0xb3, 0x85, 0x0b, 0xd2, 0x42, 0xfc, 0x42, 0xe6, 0xca, - 0x03, 0x8b, 0x7d, 0x4c, 0x8b, 0x61, 0x8e, 0x0d, 0x92, 0xac, 0x52, 0x0e, 0xe5, 0xff, 0x24, 0x60, - 0x26, 0x22, 0x17, 0x21, 0x48, 0x58, 0x7a, 0x9b, 0x20, 0x4a, 0x17, 0xd2, 0x2a, 0xfd, 0x1b, 0x15, - 0x60, 0xb2, 0xa3, 0x1b, 0xb7, 0xf4, 0x5d, 0x5c, 0x88, 0xd1, 0x64, 0xf1, 0x89, 0xce, 0x00, 0x34, - 0x71, 0x07, 0x5b, 0x4d, 0x6c, 0x19, 0x07, 0x85, 0xf8, 0x42, 0xfc, 0x42, 0x5a, 0x0d, 0xa4, 0xa0, - 0x47, 0x60, 0xba, 0xd3, 0xdb, 0x6e, 0x99, 0x86, 0x16, 0x20, 0x83, 0x85, 0xf8, 0x85, 0x09, 0x55, - 0x66, 0x19, 0x4b, 0x3e, 0xf1, 0x79, 0xc8, 0xdf, 0xc1, 0xfa, 0xad, 0x20, 0x69, 0x86, 0x92, 0x4e, - 0x91, 0xe4, 0x00, 0x61, 0x05, 0xb2, 0x6d, 0xec, 0x38, 0xfa, 0x2e, 0xd6, 0xdc, 0x83, 0x0e, 0x2e, - 0x24, 0x68, 0xeb, 0x17, 0x06, 0x5a, 0xdf, 0xdf, 0xf2, 0x0c, 0xe7, 0x6a, 0x1c, 0x74, 0x30, 0x2a, - 0x41, 0x1a, 0x5b, 0xbd, 0x36, 0x43, 0x98, 0x18, 0x22, 0xbf, 0xaa, 0xd5, 0x6b, 0xf7, 0xa3, 0xa4, - 0x08, 0x1b, 0x87, 0x98, 0x74, 0x70, 0xf7, 0xb6, 0x69, 0xe0, 0x42, 0x92, 0x02, 0x9c, 0x1f, 0x00, - 0xa8, 0xb3, 0xfc, 0x7e, 0x0c, 0xc1, 0x87, 0x2a, 0x90, 0xc6, 0xfb, 0x2e, 0xb6, 0x1c, 0xd3, 0xb6, - 0x0a, 0x93, 0x14, 0xe4, 0xc1, 0x88, 0x5e, 0xc4, 0xad, 0x66, 0x3f, 0x84, 0xcf, 0x87, 0xae, 0xc1, - 0xa4, 0xdd, 0x71, 0x4d, 0xdb, 0x72, 0x0a, 0xa9, 0x05, 0xe9, 0x42, 0xe6, 0xca, 0x7d, 0x91, 0x8a, - 0xb0, 0xce, 0x68, 0x54, 0x41, 0x8c, 0x6a, 0x20, 0x3b, 0x76, 0xaf, 0x6b, 0x60, 0xcd, 0xb0, 0x9b, - 0x58, 0x33, 0xad, 0x1d, 0xbb, 0x90, 0xa6, 0x00, 0xf3, 0x83, 0x0d, 0xa1, 0x84, 0x15, 0xbb, 0x89, - 0x6b, 0xd6, 0x8e, 0xad, 0x4e, 0x39, 0xa1, 0x6f, 0x74, 0x02, 0x92, 0xce, 0x81, 0xe5, 0xea, 0xfb, - 0x85, 0x2c, 0xd5, 0x10, 0xfe, 0x45, 0x54, 0x07, 0x37, 0x4d, 0x52, 0x5c, 0x21, 0xc7, 0x54, 0x87, - 0x7f, 0x2a, 0xbf, 0x94, 0x84, 0xfc, 0x38, 0xca, 0xf7, 0x2c, 0x4c, 0xec, 0x90, 0xf6, 0x17, 0x62, - 0x47, 0x91, 0x0e, 0xe3, 0x09, 0x8b, 0x37, 0x79, 0x8f, 0xe2, 0x2d, 0x41, 0xc6, 0xc2, 0x8e, 0x8b, - 0x9b, 0x4c, 0x57, 0xe2, 0x63, 0x6a, 0x1b, 0x30, 0xa6, 0x41, 0x65, 0x4b, 0xdc, 0x93, 0xb2, 0xbd, - 0x0c, 0x79, 0xaf, 0x4a, 0x5a, 0x57, 0xb7, 0x76, 0x85, 0xd6, 0x5e, 0x1a, 0x55, 0x93, 0xc5, 0xaa, - 0xe0, 0x53, 0x09, 0x9b, 0x3a, 0x85, 0x43, 0xdf, 0x68, 0x09, 0xc0, 0xb6, 0xb0, 0xbd, 0xa3, 0x35, - 0xb1, 0xd1, 0x2a, 0xa4, 0x86, 0x48, 0x69, 0x9d, 0x90, 0x0c, 0x48, 0xc9, 0x66, 0xa9, 0x46, 0x0b, - 0x3d, 0xe3, 0x2b, 0xe1, 0xe4, 0x10, 0x1d, 0x5a, 0x65, 0xc3, 0x6f, 0x40, 0x0f, 0x37, 0x61, 0xaa, - 0x8b, 0xc9, 0x88, 0xc0, 0x4d, 0xde, 0xb2, 0x34, 0xad, 0xc4, 0xe2, 0xc8, 0x96, 0xa9, 0x9c, 0x8d, - 0x35, 0x2c, 0xd7, 0x0d, 0x7e, 0xa2, 0x73, 0xe0, 0x25, 0x68, 0x54, 0xad, 0x80, 0xda, 0xa7, 0xac, - 0x48, 0x5c, 0xd3, 0xdb, 0x78, 0xee, 0x75, 0x98, 0x0a, 0x8b, 0x07, 0xcd, 0xc2, 0x84, 0xe3, 0xea, - 0x5d, 0x97, 0x6a, 0xe1, 0x84, 0xca, 0x3e, 0x90, 0x0c, 0x71, 0x6c, 0x35, 0xa9, 0xfd, 0x9b, 0x50, - 0xc9, 0x9f, 0xe8, 0xeb, 0xfc, 0x06, 0xc7, 0x69, 0x83, 0x1f, 0x1a, 0xec, 0xd1, 0x10, 0x72, 0x7f, - 0xbb, 0xe7, 0x9e, 0x82, 0x5c, 0xa8, 0x01, 0xe3, 0x16, 0xad, 0xfc, 0x74, 0x02, 0x8e, 0x47, 0x62, - 0xa3, 0x97, 0x61, 0xb6, 0x67, 0x99, 0x96, 0x8b, 0xbb, 0x9d, 0x2e, 0x26, 0x2a, 0xcb, 0xca, 0x2a, - 0xfc, 0xe1, 0xe4, 0x10, 0xa5, 0xdb, 0x0c, 0x52, 0x33, 0x14, 0x75, 0xa6, 0x37, 0x98, 0x88, 0x5e, - 0x81, 0x0c, 0xd1, 0x0f, 0xbd, 0xab, 0x53, 0x40, 0x36, 0x1a, 0xaf, 0x8c, 0xd7, 0xe4, 0xc5, 0x25, - 0x9f, 0xb3, 0x1c, 0x7f, 0xbf, 0x14, 0x53, 0x83, 0x58, 0x68, 0x0f, 0xb2, 0xb7, 0x71, 0xd7, 0xdc, - 0x31, 0x0d, 0x86, 0x4d, 0xc4, 0x39, 0x75, 0xe5, 0xe9, 0x31, 0xb1, 0xb7, 0x02, 0xac, 0x75, 0x57, - 0x77, 0x71, 0x11, 0x36, 0xd7, 0xb6, 0xaa, 0x6a, 0x6d, 0xb9, 0x56, 0x5d, 0x52, 0x43, 0xc8, 0x73, - 0x9f, 0x92, 0x20, 0x13, 0xa8, 0x0b, 0x31, 0x5b, 0x56, 0xaf, 0xbd, 0x8d, 0xbb, 0x5c, 0xe2, 0xfc, - 0x0b, 0x9d, 0x86, 0xf4, 0x4e, 0xaf, 0xd5, 0x62, 0x6a, 0xc3, 0xe6, 0xbc, 0x14, 0x49, 0x20, 0x2a, - 0x43, 0xac, 0x14, 0x37, 0x04, 0xd4, 0x4a, 0x91, 0xbf, 0xd1, 0x39, 0xc8, 0x98, 0x8e, 0xd6, 0xc5, - 0x1d, 0xac, 0xbb, 0xb8, 0x59, 0x48, 0x2c, 0x48, 0x17, 0x52, 0xe5, 0x58, 0x41, 0x52, 0xc1, 0x74, - 0x54, 0x9e, 0x8a, 0xe6, 0x20, 0x25, 0x74, 0xaf, 0x30, 0x41, 0x28, 0x54, 0xef, 0x9b, 0xe5, 0x71, - 0xee, 0xa4, 0xc8, 0x63, 0xdf, 0xca, 0x55, 0x98, 0x1e, 0x68, 0x24, 0xca, 0x43, 0x66, 0xa9, 0x5a, - 0x59, 0x29, 0xa9, 0xa5, 0x46, 0x6d, 0x7d, 0x4d, 0x3e, 0x86, 0xa6, 0x20, 0xd0, 0x6e, 0x59, 0xba, - 0x98, 0x4e, 0x7d, 0x7e, 0x52, 0x7e, 0xef, 0x7b, 0xdf, 0xfb, 0xde, 0x98, 0xf2, 0x2b, 0x49, 0x98, - 0x8d, 0xb2, 0x72, 0x91, 0x06, 0xd7, 0x97, 0x49, 0x3c, 0x24, 0x93, 0x12, 0x4c, 0xb4, 0xf4, 0x6d, - 0xdc, 0xa2, 0x8d, 0x9b, 0xba, 0xf2, 0xc8, 0x58, 0x76, 0x74, 0x71, 0x85, 0xb0, 0xa8, 0x8c, 0x13, - 0xbd, 0xc0, 0x25, 0x37, 0x41, 0x11, 0x2e, 0x8e, 0x87, 0x40, 0xac, 0x1f, 0x97, 0xf2, 0x69, 0x48, - 0x93, 0xff, 0x59, 0xb7, 0x24, 0x59, 0xb7, 0x90, 0x04, 0xda, 0x2d, 0x73, 0x90, 0xa2, 0x86, 0xad, - 0x89, 0xbd, 0x2e, 0x13, 0xdf, 0xc4, 0x14, 0x34, 0xf1, 0x8e, 0xde, 0x6b, 0xb9, 0xda, 0x6d, 0xbd, - 0xd5, 0xc3, 0xd4, 0x44, 0xa5, 0xd5, 0x2c, 0x4f, 0xdc, 0x22, 0x69, 0x68, 0x1e, 0x32, 0xcc, 0x0e, - 0x9a, 0x56, 0x13, 0xef, 0xd3, 0x99, 0x70, 0x42, 0x65, 0xa6, 0xb1, 0x46, 0x52, 0x48, 0xf1, 0xaf, - 0x39, 0xb6, 0x25, 0x8c, 0x09, 0x2d, 0x82, 0x24, 0xd0, 0xe2, 0x9f, 0xea, 0x9f, 0x84, 0xef, 0x8f, - 0x6e, 0xde, 0x80, 0xf5, 0x3b, 0x0f, 0x79, 0x4a, 0xf1, 0x04, 0x1f, 0xab, 0x7a, 0xab, 0x30, 0x4d, - 0x15, 0x60, 0x8a, 0x25, 0xaf, 0xf3, 0x54, 0xe5, 0x17, 0x62, 0x90, 0xa0, 0x53, 0x41, 0x1e, 0x32, - 0x8d, 0x57, 0x36, 0xaa, 0xda, 0xd2, 0xfa, 0x66, 0x79, 0xa5, 0x2a, 0x4b, 0xa4, 0xeb, 0x69, 0xc2, - 0xf2, 0xca, 0x7a, 0xa9, 0x21, 0xc7, 0xbc, 0xef, 0xda, 0x5a, 0xe3, 0xda, 0x55, 0x39, 0xee, 0x31, - 0x6c, 0xb2, 0x84, 0x44, 0x90, 0xe0, 0x89, 0x2b, 0xf2, 0x04, 0x92, 0x21, 0xcb, 0x00, 0x6a, 0x2f, - 0x57, 0x97, 0xae, 0x5d, 0x95, 0x93, 0xe1, 0x94, 0x27, 0xae, 0xc8, 0x93, 0x28, 0x07, 0x69, 0x9a, - 0x52, 0x5e, 0x5f, 0x5f, 0x91, 0x53, 0x1e, 0x66, 0xbd, 0xa1, 0xd6, 0xd6, 0xae, 0xcb, 0x69, 0x0f, - 0xf3, 0xba, 0xba, 0xbe, 0xb9, 0x21, 0x83, 0x87, 0xb0, 0x5a, 0xad, 0xd7, 0x4b, 0xd7, 0xab, 0x72, - 0xc6, 0xa3, 0x28, 0xbf, 0xd2, 0xa8, 0xd6, 0xe5, 0x6c, 0xa8, 0x5a, 0x4f, 0x5c, 0x91, 0x73, 0x5e, - 0x11, 0xd5, 0xb5, 0xcd, 0x55, 0x79, 0x0a, 0x4d, 0x43, 0x8e, 0x15, 0x21, 0x2a, 0x91, 0xef, 0x4b, - 0xba, 0x76, 0x55, 0x96, 0xfd, 0x8a, 0x30, 0x94, 0xe9, 0x50, 0xc2, 0xb5, 0xab, 0x32, 0x52, 0x2a, - 0x30, 0x41, 0xd5, 0x10, 0x21, 0x98, 0x5a, 0x29, 0x95, 0xab, 0x2b, 0xda, 0xfa, 0x06, 0x19, 0x34, - 0xa5, 0x15, 0x59, 0xf2, 0xd3, 0xd4, 0xea, 0xbb, 0x36, 0x6b, 0x6a, 0x75, 0x49, 0x8e, 0x05, 0xd3, - 0x36, 0xaa, 0xa5, 0x46, 0x75, 0x49, 0x8e, 0x2b, 0x06, 0xcc, 0x46, 0x4d, 0x81, 0x91, 0x43, 0x28, - 0xa0, 0x0b, 0xb1, 0x21, 0xba, 0x40, 0xb1, 0xfa, 0x75, 0x41, 0xf9, 0x5c, 0x0c, 0x66, 0x22, 0xdc, - 0x80, 0xc8, 0x42, 0x5e, 0x84, 0x09, 0xa6, 0xcb, 0xcc, 0x14, 0x3f, 0x1c, 0xe9, 0x4f, 0x50, 0xcd, - 0x1e, 0x70, 0x8e, 0x28, 0x5f, 0xd0, 0x6d, 0x8c, 0x0f, 0x71, 0x1b, 0x09, 0xc4, 0x80, 0xc2, 0x7e, - 0xe3, 0xc0, 0x74, 0xcd, 0x3c, 0x9a, 0x6b, 0xe3, 0x78, 0x34, 0x34, 0xed, 0x68, 0xd3, 0xf6, 0x44, - 0xc4, 0xb4, 0xfd, 0x2c, 0x4c, 0x0f, 0x00, 0x8d, 0x3d, 0x7d, 0x7e, 0xab, 0x04, 0x85, 0x61, 0xc2, - 0x19, 0x61, 0x12, 0x63, 0x21, 0x93, 0xf8, 0x6c, 0xbf, 0x04, 0xcf, 0x0e, 0xef, 0x84, 0x81, 0xbe, - 0xfe, 0xb8, 0x04, 0x27, 0xa2, 0x97, 0x07, 0x91, 0x75, 0x78, 0x01, 0x92, 0x6d, 0xec, 0xee, 0xd9, - 0xc2, 0x11, 0x7e, 0x28, 0xc2, 0xbd, 0x22, 0xd9, 0xfd, 0x9d, 0xcd, 0xb9, 0x82, 0xfe, 0x59, 0x7c, - 0x98, 0x8f, 0xcf, 0x6a, 0x33, 0x50, 0xd3, 0xef, 0x88, 0xc1, 0xf1, 0x48, 0xf0, 0xc8, 0x8a, 0xde, - 0x0f, 0x60, 0x5a, 0x9d, 0x9e, 0xcb, 0x9c, 0x5d, 0x66, 0x89, 0xd3, 0x34, 0x85, 0x1a, 0x2f, 0x62, - 0x65, 0x7b, 0xae, 0x97, 0xcf, 0x26, 0x51, 0x60, 0x49, 0x94, 0xe0, 0x69, 0xbf, 0xa2, 0x09, 0x5a, - 0xd1, 0x33, 0x43, 0x5a, 0x3a, 0xa0, 0x98, 0x8f, 0x83, 0x6c, 0xb4, 0x4c, 0x6c, 0xb9, 0x9a, 0xe3, - 0x76, 0xb1, 0xde, 0x36, 0xad, 0x5d, 0x36, 0xcf, 0x16, 0x27, 0x76, 0xf4, 0x96, 0x83, 0xd5, 0x3c, - 0xcb, 0xae, 0x8b, 0x5c, 0xc2, 0x41, 0x15, 0xa8, 0x1b, 0xe0, 0x48, 0x86, 0x38, 0x58, 0xb6, 0xc7, - 0xa1, 0x7c, 0x6f, 0x1a, 0x32, 0x81, 0xc5, 0x14, 0x3a, 0x0b, 0xd9, 0xd7, 0xf4, 0xdb, 0xba, 0x26, - 0x16, 0xc8, 0x4c, 0x12, 0x19, 0x92, 0xb6, 0xc1, 0x17, 0xc9, 0x8f, 0xc3, 0x2c, 0x25, 0xb1, 0x7b, - 0x2e, 0xee, 0x6a, 0x46, 0x4b, 0x77, 0x1c, 0x2a, 0xb4, 0x14, 0x25, 0x45, 0x24, 0x6f, 0x9d, 0x64, - 0x55, 0x44, 0x0e, 0x7a, 0x12, 0x66, 0x28, 0x47, 0xbb, 0xd7, 0x72, 0xcd, 0x4e, 0x0b, 0x6b, 0x64, - 0xc9, 0xee, 0xd0, 0x29, 0xc7, 0xab, 0xd9, 0x34, 0xa1, 0x58, 0xe5, 0x04, 0xa4, 0x46, 0x0e, 0x5a, - 0x82, 0xfb, 0x29, 0xdb, 0x2e, 0xb6, 0x70, 0x57, 0x77, 0xb1, 0x86, 0xdf, 0xd3, 0xd3, 0x5b, 0x8e, - 0xa6, 0x5b, 0x4d, 0x6d, 0x4f, 0x77, 0xf6, 0x0a, 0xb3, 0x9e, 0x5b, 0x72, 0x8a, 0x10, 0x5e, 0xe7, - 0x74, 0x55, 0x4a, 0x56, 0xb2, 0x9a, 0x37, 0x74, 0x67, 0x0f, 0x15, 0xe1, 0x04, 0x45, 0x71, 0xdc, - 0xae, 0x69, 0xed, 0x6a, 0xc6, 0x1e, 0x36, 0x6e, 0x69, 0x3d, 0x77, 0xe7, 0xe9, 0xc2, 0xe9, 0x60, - 0xf9, 0xb4, 0x86, 0x75, 0x4a, 0x53, 0x21, 0x24, 0x9b, 0xee, 0xce, 0xd3, 0xa8, 0x0e, 0x59, 0xd2, - 0x19, 0x6d, 0xf3, 0x75, 0xac, 0xed, 0xd8, 0x5d, 0x3a, 0x87, 0x4e, 0x45, 0x98, 0xa6, 0x80, 0x04, - 0x17, 0xd7, 0x39, 0xc3, 0xaa, 0xdd, 0xc4, 0xc5, 0x89, 0xfa, 0x46, 0xb5, 0xba, 0xa4, 0x66, 0x04, - 0xca, 0xb2, 0xdd, 0x25, 0x0a, 0xb5, 0x6b, 0x7b, 0x02, 0xce, 0x30, 0x85, 0xda, 0xb5, 0x85, 0x78, - 0x9f, 0x84, 0x19, 0xc3, 0x60, 0x6d, 0x36, 0x0d, 0x8d, 0x2f, 0xac, 0x9d, 0x82, 0x1c, 0x12, 0x96, - 0x61, 0x5c, 0x67, 0x04, 0x5c, 0xc7, 0x1d, 0xf4, 0x0c, 0x1c, 0xf7, 0x85, 0x15, 0x64, 0x9c, 0x1e, - 0x68, 0x65, 0x3f, 0xeb, 0x93, 0x30, 0xd3, 0x39, 0x18, 0x64, 0x44, 0xa1, 0x12, 0x3b, 0x07, 0xfd, - 0x6c, 0x4f, 0xc1, 0x6c, 0x67, 0xaf, 0x33, 0xc8, 0x77, 0x31, 0xc8, 0x87, 0x3a, 0x7b, 0x9d, 0x7e, - 0xc6, 0x07, 0x69, 0x94, 0xa5, 0x8b, 0x0d, 0xea, 0x1d, 0x9e, 0x0c, 0x92, 0x07, 0x32, 0xd0, 0x22, - 0xc8, 0x86, 0xa1, 0x61, 0x4b, 0xdf, 0x6e, 0x61, 0x4d, 0xef, 0x62, 0x4b, 0x77, 0x0a, 0xf3, 0x94, - 0x38, 0xe1, 0x76, 0x7b, 0x58, 0x9d, 0x32, 0x8c, 0x2a, 0xcd, 0x2c, 0xd1, 0x3c, 0x74, 0x11, 0xa6, - 0xed, 0xed, 0xd7, 0x0c, 0xa6, 0x91, 0x5a, 0xa7, 0x8b, 0x77, 0xcc, 0xfd, 0xc2, 0x03, 0x54, 0xbc, - 0x79, 0x92, 0x41, 0xf5, 0x71, 0x83, 0x26, 0xa3, 0x87, 0x41, 0x36, 0x9c, 0x3d, 0xbd, 0xdb, 0xa1, - 0x26, 0xd9, 0xe9, 0xe8, 0x06, 0x2e, 0x3c, 0xc8, 0x48, 0x59, 0xfa, 0x9a, 0x48, 0x26, 0x23, 0xc2, - 0xb9, 0x63, 0xee, 0xb8, 0x02, 0xf1, 0x3c, 0x1b, 0x11, 0x34, 0x8d, 0xa3, 0x5d, 0x00, 0x99, 0x48, - 0x22, 0x54, 0xf0, 0x05, 0x4a, 0x36, 0xd5, 0xd9, 0xeb, 0x04, 0xcb, 0x3d, 0x07, 0x39, 0x42, 0xe9, - 0x17, 0xfa, 0x30, 0x73, 0xdc, 0x3a, 0x7b, 0x81, 0x12, 0xaf, 0xc2, 0x09, 0x42, 0xd4, 0xc6, 0xae, - 0xde, 0xd4, 0x5d, 0x3d, 0x40, 0xfd, 0x28, 0xa5, 0x26, 0x62, 0x5f, 0xe5, 0x99, 0xa1, 0x7a, 0x76, - 0x7b, 0xdb, 0x07, 0x9e, 0x62, 0x3d, 0xc6, 0xea, 0x49, 0xd2, 0x84, 0x6a, 0xbd, 0x63, 0xab, 0x29, - 0xa5, 0x08, 0xd9, 0xa0, 0xde, 0xa3, 0x34, 0x30, 0xcd, 0x97, 0x25, 0xe2, 0x04, 0x55, 0xd6, 0x97, - 0x88, 0xfb, 0xf2, 0x6a, 0x55, 0x8e, 0x11, 0x37, 0x6a, 0xa5, 0xd6, 0xa8, 0x6a, 0xea, 0xe6, 0x5a, - 0xa3, 0xb6, 0x5a, 0x95, 0xe3, 0x01, 0xc7, 0xfe, 0x66, 0x22, 0xf5, 0x90, 0x7c, 0x5e, 0xf9, 0xe5, - 0x38, 0x4c, 0x85, 0xd7, 0xd6, 0xe8, 0x39, 0x38, 0x29, 0x42, 0x64, 0x0e, 0x76, 0xb5, 0x3b, 0x66, - 0x97, 0x0e, 0xc8, 0xb6, 0xce, 0x26, 0x47, 0x4f, 0x7f, 0x66, 0x39, 0x55, 0x1d, 0xbb, 0xef, 0x36, - 0xbb, 0x64, 0xb8, 0xb5, 0x75, 0x17, 0xad, 0xc0, 0xbc, 0x65, 0x6b, 0x8e, 0xab, 0x5b, 0x4d, 0xbd, - 0xdb, 0xd4, 0xfc, 0xe0, 0xa4, 0xa6, 0x1b, 0x06, 0x76, 0x1c, 0x9b, 0x4d, 0x84, 0x1e, 0xca, 0x7d, - 0x96, 0x5d, 0xe7, 0xc4, 0xfe, 0x0c, 0x51, 0xe2, 0xa4, 0x7d, 0xea, 0x1b, 0x1f, 0xa6, 0xbe, 0xa7, - 0x21, 0xdd, 0xd6, 0x3b, 0x1a, 0xb6, 0xdc, 0xee, 0x01, 0xf5, 0xcf, 0x53, 0x6a, 0xaa, 0xad, 0x77, - 0xaa, 0xe4, 0x1b, 0x6d, 0xc1, 0x43, 0x3e, 0xa9, 0xd6, 0xc2, 0xbb, 0xba, 0x71, 0xa0, 0x51, 0x67, - 0x9c, 0x06, 0x7a, 0x34, 0xc3, 0xb6, 0x76, 0x5a, 0xa6, 0xe1, 0x3a, 0xd4, 0x3e, 0x30, 0x1b, 0xa7, - 0xf8, 0x1c, 0x2b, 0x94, 0xe1, 0xa6, 0x63, 0x5b, 0xd4, 0x07, 0xaf, 0x08, 0xea, 0x77, 0xae, 0x87, - 0xc3, 0xbd, 0x94, 0x90, 0x27, 0x6e, 0x26, 0x52, 0x13, 0x72, 0xf2, 0x66, 0x22, 0x95, 0x94, 0x27, - 0x6f, 0x26, 0x52, 0x29, 0x39, 0x7d, 0x33, 0x91, 0x4a, 0xcb, 0xa0, 0xbc, 0x2f, 0x0d, 0xd9, 0xe0, - 0xca, 0x80, 0x2c, 0xb4, 0x0c, 0x3a, 0x37, 0x4a, 0xd4, 0x7a, 0x9e, 0x3b, 0x74, 0x1d, 0xb1, 0x58, - 0x21, 0x93, 0x66, 0x31, 0xc9, 0xdc, 0x70, 0x95, 0x71, 0x12, 0x87, 0x85, 0xa8, 0x35, 0x66, 0x6e, - 0x4f, 0x4a, 0xe5, 0x5f, 0xe8, 0x3a, 0x24, 0x5f, 0x73, 0x28, 0x76, 0x92, 0x62, 0x3f, 0x70, 0x38, - 0xf6, 0xcd, 0x3a, 0x05, 0x4f, 0xdf, 0xac, 0x6b, 0x6b, 0xeb, 0xea, 0x6a, 0x69, 0x45, 0xe5, 0xec, - 0xe8, 0x14, 0x24, 0x5a, 0xfa, 0xeb, 0x07, 0xe1, 0xe9, 0x95, 0x26, 0xa1, 0x45, 0xc8, 0xf7, 0x2c, - 0xb6, 0xea, 0x26, 0x5d, 0x45, 0xa8, 0xf2, 0x41, 0xaa, 0x29, 0x3f, 0x77, 0x85, 0xd0, 0x8f, 0xa9, - 0x1e, 0xa7, 0x20, 0x71, 0x07, 0xeb, 0xb7, 0xc2, 0x93, 0x20, 0x4d, 0x42, 0x17, 0x20, 0xdb, 0xc4, - 0xdb, 0xbd, 0x5d, 0xad, 0x8b, 0x9b, 0xba, 0xe1, 0x86, 0x4d, 0x7f, 0x86, 0x66, 0xa9, 0x34, 0x07, - 0xbd, 0x04, 0x69, 0xd2, 0x47, 0x16, 0xed, 0xe3, 0x69, 0x2a, 0x82, 0xc7, 0x0e, 0x17, 0x01, 0xef, - 0x62, 0xc1, 0xa4, 0xfa, 0xfc, 0xe8, 0x26, 0x24, 0x5d, 0xbd, 0xbb, 0x8b, 0x5d, 0x6a, 0xf9, 0xa7, - 0x22, 0xc2, 0x55, 0x11, 0x48, 0x0d, 0xca, 0x41, 0xc4, 0x4a, 0x75, 0x94, 0x23, 0xa0, 0x1b, 0x30, - 0xc9, 0xfe, 0x72, 0x0a, 0x33, 0x0b, 0xf1, 0xa3, 0x83, 0xa9, 0x82, 0xfd, 0x1d, 0xb4, 0x59, 0x97, - 0x60, 0x82, 0x2a, 0x1b, 0x02, 0xe0, 0xea, 0x26, 0x1f, 0x43, 0x29, 0x48, 0x54, 0xd6, 0x55, 0x62, - 0xb7, 0x64, 0xc8, 0xb2, 0x54, 0x6d, 0xa3, 0x56, 0xad, 0x54, 0xe5, 0x98, 0xf2, 0x24, 0x24, 0x99, - 0x06, 0x11, 0x9b, 0xe6, 0xe9, 0x90, 0x7c, 0x8c, 0x7f, 0x72, 0x0c, 0x49, 0xe4, 0x6e, 0xae, 0x96, - 0xab, 0xaa, 0x1c, 0x53, 0x36, 0x21, 0xdf, 0x27, 0x75, 0x74, 0x1c, 0xa6, 0xd5, 0x6a, 0xa3, 0xba, - 0x46, 0x56, 0x6d, 0xda, 0xe6, 0xda, 0x4b, 0x6b, 0xeb, 0xef, 0x5e, 0x93, 0x8f, 0x85, 0x93, 0x85, - 0x81, 0x94, 0xd0, 0x2c, 0xc8, 0x7e, 0x72, 0x7d, 0x7d, 0x53, 0xa5, 0xb5, 0xf9, 0xae, 0x18, 0xc8, - 0xfd, 0x62, 0x43, 0x27, 0x61, 0xa6, 0x51, 0x52, 0xaf, 0x57, 0x1b, 0x1a, 0x5b, 0x89, 0x7a, 0xd0, - 0xb3, 0x20, 0x07, 0x33, 0x96, 0x6b, 0x74, 0xa1, 0x3d, 0x0f, 0xa7, 0x83, 0xa9, 0xd5, 0x97, 0x1b, - 0xd5, 0xb5, 0x3a, 0x2d, 0xbc, 0xb4, 0x76, 0x9d, 0x58, 0xeb, 0x3e, 0x3c, 0xb1, 0xf6, 0x8d, 0x93, - 0xaa, 0x86, 0xf1, 0xaa, 0x2b, 0x4b, 0x72, 0xa2, 0x3f, 0x79, 0x7d, 0xad, 0xba, 0xbe, 0x2c, 0x4f, - 0xf4, 0x97, 0x4e, 0xd7, 0xc3, 0x49, 0x34, 0x07, 0x27, 0xfa, 0x53, 0xb5, 0xea, 0x5a, 0x43, 0x7d, - 0x45, 0x9e, 0xec, 0x2f, 0xb8, 0x5e, 0x55, 0xb7, 0x6a, 0x95, 0xaa, 0x9c, 0x42, 0x27, 0x00, 0x85, - 0x6b, 0xd4, 0xb8, 0xb1, 0xbe, 0x24, 0xa7, 0x07, 0xec, 0x93, 0xe2, 0x40, 0x36, 0xb8, 0x28, 0xfd, - 0xaa, 0x98, 0x46, 0xe5, 0x83, 0x31, 0xc8, 0x04, 0x16, 0x99, 0x64, 0x75, 0xa0, 0xb7, 0x5a, 0xf6, - 0x1d, 0x4d, 0x6f, 0x99, 0xba, 0xc3, 0xad, 0x17, 0xd0, 0xa4, 0x12, 0x49, 0x19, 0xd7, 0x5a, 0x8c, - 0x3f, 0x5f, 0x24, 0xbf, 0x16, 0xe7, 0x8b, 0x09, 0x39, 0xa9, 0x7c, 0x54, 0x02, 0xb9, 0x7f, 0xf5, - 0xd8, 0xd7, 0x7c, 0x69, 0x58, 0xf3, 0xbf, 0x2a, 0x7d, 0xf7, 0x11, 0x09, 0xa6, 0xc2, 0x4b, 0xc6, - 0xbe, 0xea, 0x9d, 0xfd, 0x2b, 0xad, 0xde, 0xef, 0xc5, 0x20, 0x17, 0x5a, 0x28, 0x8e, 0x5b, 0xbb, - 0xf7, 0xc0, 0xb4, 0xd9, 0xc4, 0xed, 0x8e, 0xed, 0x62, 0xcb, 0x38, 0xd0, 0x5a, 0xf8, 0x36, 0x6e, - 0x15, 0x14, 0x6a, 0xe2, 0x2f, 0x1d, 0xbe, 0x14, 0x5d, 0xac, 0xf9, 0x7c, 0x2b, 0x84, 0xad, 0x38, - 0x53, 0x5b, 0xaa, 0xae, 0x6e, 0xac, 0x37, 0xaa, 0x6b, 0x95, 0x57, 0x84, 0x75, 0x51, 0x65, 0xb3, - 0x8f, 0xec, 0x1d, 0x34, 0xda, 0x1b, 0x20, 0xf7, 0x57, 0x8a, 0xd8, 0x8a, 0x88, 0x6a, 0xc9, 0xc7, - 0xd0, 0x0c, 0xe4, 0xd7, 0xd6, 0xb5, 0x7a, 0x6d, 0xa9, 0xaa, 0x55, 0x97, 0x97, 0xab, 0x95, 0x46, - 0x9d, 0x05, 0x17, 0x3d, 0xea, 0x86, 0x1c, 0x0b, 0x8a, 0xf8, 0x43, 0x71, 0x98, 0x89, 0xa8, 0x09, - 0x2a, 0xf1, 0xb0, 0x00, 0x8b, 0x54, 0x3c, 0x36, 0x4e, 0xed, 0x17, 0x89, 0x63, 0xbe, 0xa1, 0x77, - 0x5d, 0x1e, 0x45, 0x78, 0x18, 0x88, 0x94, 0x2c, 0x97, 0xf8, 0x09, 0x5d, 0x1e, 0xb4, 0x65, 0xb1, - 0x82, 0xbc, 0x9f, 0xce, 0xe2, 0xb6, 0x8f, 0x02, 0xea, 0xd8, 0x8e, 0xe9, 0x9a, 0xb7, 0xb1, 0x66, - 0x5a, 0x22, 0xc2, 0x9b, 0x58, 0x90, 0x2e, 0x24, 0x54, 0x59, 0xe4, 0xd4, 0x2c, 0xd7, 0xa3, 0xb6, - 0xf0, 0xae, 0xde, 0x47, 0x4d, 0xfc, 0x98, 0xb8, 0x2a, 0x8b, 0x1c, 0x8f, 0xfa, 0x2c, 0x64, 0x9b, - 0x76, 0x8f, 0x2c, 0xa8, 0x18, 0x1d, 0xb1, 0x16, 0x92, 0x9a, 0x61, 0x69, 0x1e, 0x09, 0x5f, 0x2a, - 0xfb, 0xa1, 0xe5, 0xac, 0x9a, 0x61, 0x69, 0x8c, 0xe4, 0x3c, 0xe4, 0xf5, 0xdd, 0xdd, 0x2e, 0x01, - 0x17, 0x40, 0x6c, 0xf1, 0x3f, 0xe5, 0x25, 0x53, 0xc2, 0xb9, 0x9b, 0x90, 0x12, 0x72, 0x20, 0xfe, - 0x30, 0x91, 0x84, 0xd6, 0x61, 0x11, 0xad, 0xd8, 0x85, 0xb4, 0x9a, 0xb2, 0x44, 0xe6, 0x59, 0xc8, - 0x9a, 0x8e, 0xe6, 0xef, 0x6d, 0xc6, 0x16, 0x62, 0x17, 0x52, 0x6a, 0xc6, 0x74, 0xbc, 0x3d, 0x12, - 0xe5, 0xe3, 0x31, 0x98, 0x0a, 0xef, 0xda, 0xa2, 0x25, 0x48, 0xb5, 0x6c, 0xbe, 0xc9, 0xc2, 0x8e, - 0x0c, 0x5c, 0x18, 0xb1, 0xd1, 0xbb, 0xb8, 0xc2, 0xe9, 0x55, 0x8f, 0x73, 0xee, 0x37, 0x25, 0x48, - 0x89, 0x64, 0x74, 0x02, 0x12, 0x1d, 0xdd, 0xdd, 0xa3, 0x70, 0x13, 0xe5, 0x98, 0x2c, 0xa9, 0xf4, - 0x9b, 0xa4, 0x3b, 0x1d, 0x9d, 0xed, 0x13, 0xf1, 0x74, 0xf2, 0x4d, 0xfa, 0xb5, 0x85, 0xf5, 0x26, - 0x8d, 0x2c, 0xd8, 0xed, 0x36, 0xb6, 0x5c, 0x47, 0xf4, 0x2b, 0x4f, 0xaf, 0xf0, 0x64, 0xf4, 0x08, - 0x4c, 0xbb, 0x5d, 0xdd, 0x6c, 0x85, 0x68, 0x13, 0x94, 0x56, 0x16, 0x19, 0x1e, 0x71, 0x11, 0x4e, - 0x09, 0xdc, 0x26, 0x76, 0x75, 0x63, 0x0f, 0x37, 0x7d, 0xa6, 0x24, 0x8d, 0x20, 0x9e, 0xe4, 0x04, - 0x4b, 0x3c, 0x5f, 0xf0, 0x2a, 0x9f, 0x89, 0xc1, 0xb4, 0x88, 0x85, 0x34, 0x3d, 0x61, 0xad, 0x02, - 0xe8, 0x96, 0x65, 0xbb, 0x41, 0x71, 0x0d, 0xaa, 0xf2, 0x00, 0xdf, 0x62, 0xc9, 0x63, 0x52, 0x03, - 0x00, 0x73, 0x5f, 0x90, 0x00, 0xfc, 0xac, 0xa1, 0x72, 0x9b, 0x87, 0x0c, 0xdf, 0x93, 0xa7, 0x07, - 0x3b, 0x58, 0xf8, 0x0c, 0x58, 0xd2, 0xb2, 0xd9, 0xa2, 0x41, 0xce, 0x6d, 0xbc, 0x6b, 0x5a, 0x7c, - 0x77, 0x86, 0x7d, 0x88, 0x20, 0x67, 0xc2, 0xdf, 0x9e, 0x54, 0x21, 0xe5, 0xe0, 0xb6, 0x6e, 0xb9, - 0xa6, 0xc1, 0xf7, 0x5b, 0xae, 0x1d, 0xa9, 0xf2, 0x8b, 0x75, 0xce, 0xad, 0x7a, 0x38, 0xca, 0x05, - 0x48, 0x89, 0x54, 0xe2, 0xf8, 0xad, 0xad, 0xaf, 0x55, 0xe5, 0x63, 0x68, 0x12, 0xe2, 0xf5, 0x6a, - 0x43, 0x96, 0xc8, 0x22, 0xb6, 0xb4, 0x52, 0x2b, 0xd5, 0xe5, 0x58, 0xf9, 0x6f, 0xc3, 0x8c, 0x61, - 0xb7, 0xfb, 0x0b, 0x2c, 0xcb, 0x7d, 0x01, 0x44, 0xe7, 0x86, 0xf4, 0xea, 0x63, 0x9c, 0x68, 0xd7, - 0x6e, 0xe9, 0xd6, 0xee, 0xa2, 0xdd, 0xdd, 0xf5, 0x8f, 0xc5, 0x90, 0xb5, 0x86, 0x13, 0x38, 0x1c, - 0xd3, 0xd9, 0xfe, 0x4b, 0x49, 0xfa, 0xd1, 0x58, 0xfc, 0xfa, 0x46, 0xf9, 0x27, 0x63, 0x73, 0xd7, - 0x19, 0xe3, 0x86, 0x68, 0x8e, 0x8a, 0x77, 0x5a, 0xd8, 0x20, 0x95, 0x87, 0x3f, 0x7e, 0x04, 0x66, - 0x77, 0xed, 0x5d, 0x9b, 0x22, 0x5d, 0x22, 0x7f, 0xf1, 0x73, 0x35, 0x69, 0x2f, 0x75, 0x6e, 0xe4, - 0x21, 0x9c, 0xe2, 0x1a, 0xcc, 0x70, 0x62, 0x8d, 0x6e, 0xdf, 0xb3, 0x50, 0x05, 0x3a, 0x34, 0x4e, - 0x5e, 0xf8, 0xb9, 0x3f, 0xa0, 0x5e, 0x89, 0x3a, 0xcd, 0x59, 0x49, 0x1e, 0x8b, 0x66, 0x14, 0x55, - 0x38, 0x1e, 0xc2, 0x63, 0x36, 0x02, 0x77, 0x47, 0x20, 0xfe, 0x5b, 0x8e, 0x38, 0x13, 0x40, 0xac, - 0x73, 0xd6, 0x62, 0x05, 0x72, 0x47, 0xc1, 0xfa, 0x55, 0x8e, 0x95, 0xc5, 0x41, 0x90, 0xeb, 0x90, - 0xa7, 0x20, 0x46, 0xcf, 0x71, 0xed, 0x36, 0x35, 0xc0, 0x87, 0xc3, 0xfc, 0xbb, 0x3f, 0x60, 0x83, - 0x76, 0x8a, 0xb0, 0x55, 0x3c, 0xae, 0x62, 0x11, 0xe8, 0x89, 0x85, 0x26, 0x36, 0x5a, 0x23, 0x10, - 0x7e, 0x8d, 0x57, 0xc4, 0xa3, 0x2f, 0x6e, 0xc1, 0x2c, 0xf9, 0x9b, 0xda, 0xc7, 0x60, 0x4d, 0x46, - 0x07, 0xd5, 0x0b, 0xff, 0xe9, 0x5b, 0x99, 0x5d, 0x98, 0xf1, 0x00, 0x02, 0x75, 0x0a, 0xf4, 0xe2, - 0x2e, 0x76, 0x5d, 0xdc, 0x75, 0x34, 0xbd, 0x15, 0x55, 0xbd, 0x40, 0x54, 0xb2, 0xf0, 0x43, 0x5f, - 0x0c, 0xf7, 0xe2, 0x75, 0xc6, 0x59, 0x6a, 0xb5, 0x8a, 0x9b, 0x70, 0x32, 0x42, 0x2b, 0xc6, 0xc0, - 0xfc, 0x10, 0xc7, 0x9c, 0x1d, 0xd0, 0x0c, 0x02, 0xbb, 0x01, 0x22, 0xdd, 0xeb, 0xcb, 0x31, 0x30, - 0x3f, 0xcc, 0x31, 0x11, 0xe7, 0x15, 0x5d, 0x4a, 0x10, 0x6f, 0xc2, 0xf4, 0x6d, 0xdc, 0xdd, 0xb6, - 0x1d, 0x1e, 0x09, 0x1e, 0x03, 0xee, 0x23, 0x1c, 0x2e, 0xcf, 0x19, 0x69, 0x68, 0x98, 0x60, 0x3d, - 0x03, 0xa9, 0x1d, 0xdd, 0xc0, 0x63, 0x40, 0xdc, 0xe5, 0x10, 0x93, 0x84, 0x9e, 0xb0, 0x96, 0x20, - 0xbb, 0x6b, 0xf3, 0x29, 0x72, 0x34, 0xfb, 0x47, 0x39, 0x7b, 0x46, 0xf0, 0x70, 0x88, 0x8e, 0xdd, - 0xe9, 0xb5, 0xc8, 0xfc, 0x39, 0x1a, 0xe2, 0x87, 0x05, 0x84, 0xe0, 0xe1, 0x10, 0x47, 0x10, 0xeb, - 0xc7, 0x04, 0x84, 0x13, 0x90, 0xe7, 0x8b, 0x90, 0xb1, 0xad, 0xd6, 0x81, 0x6d, 0x8d, 0x53, 0x89, - 0x1f, 0xe1, 0x08, 0xc0, 0x59, 0x08, 0xc0, 0xb3, 0x90, 0x1e, 0xb7, 0x23, 0x7e, 0xfc, 0x8b, 0x62, - 0x78, 0x88, 0x1e, 0xb8, 0x0e, 0x79, 0x61, 0xa0, 0x4c, 0xdb, 0x1a, 0x03, 0xe2, 0x27, 0x38, 0xc4, - 0x54, 0x80, 0x8d, 0x37, 0xc3, 0xc5, 0x8e, 0xbb, 0x8b, 0xc7, 0x01, 0xf9, 0xb8, 0x68, 0x06, 0x67, - 0xe1, 0xa2, 0xdc, 0xc6, 0x96, 0xb1, 0x37, 0x1e, 0xc2, 0x27, 0x84, 0x28, 0x05, 0x0f, 0x81, 0xa8, - 0x40, 0xae, 0xad, 0x77, 0x9d, 0x3d, 0xbd, 0x35, 0x56, 0x77, 0x7c, 0x92, 0x63, 0x64, 0x3d, 0x26, - 0x2e, 0x91, 0x9e, 0x75, 0x14, 0x98, 0x9f, 0x14, 0x12, 0x09, 0xb0, 0xf1, 0xa1, 0xe7, 0xb8, 0x34, - 0x6c, 0x7e, 0x14, 0xb4, 0x9f, 0x12, 0x43, 0x8f, 0xf1, 0xae, 0x06, 0x11, 0x9f, 0x85, 0xb4, 0x63, - 0xbe, 0x3e, 0x16, 0xcc, 0x3f, 0x12, 0x3d, 0x4d, 0x19, 0x08, 0xf3, 0x2b, 0x70, 0x2a, 0x72, 0x9a, - 0x18, 0x03, 0xec, 0xa7, 0x39, 0xd8, 0x89, 0x88, 0xa9, 0x82, 0x9b, 0x84, 0xa3, 0x42, 0xfe, 0x8c, - 0x30, 0x09, 0xb8, 0x0f, 0x6b, 0x83, 0x2c, 0x5a, 0x1c, 0x7d, 0xe7, 0x68, 0x52, 0xfb, 0xc7, 0x42, - 0x6a, 0x8c, 0x37, 0x24, 0xb5, 0x06, 0x9c, 0xe0, 0x88, 0x47, 0xeb, 0xd7, 0x9f, 0x15, 0x86, 0x95, - 0x71, 0x6f, 0x86, 0x7b, 0xf7, 0xeb, 0x61, 0xce, 0x13, 0xa7, 0xf0, 0x8e, 0x1d, 0xad, 0xad, 0x77, - 0xc6, 0x40, 0xfe, 0x39, 0x8e, 0x2c, 0x2c, 0xbe, 0xe7, 0x5e, 0x3b, 0xab, 0x7a, 0x87, 0x80, 0xbf, - 0x0c, 0x05, 0x01, 0xde, 0xb3, 0xba, 0xd8, 0xb0, 0x77, 0x2d, 0xf3, 0x75, 0xdc, 0x1c, 0x03, 0xfa, - 0x9f, 0xf4, 0x75, 0xd5, 0x66, 0x80, 0x9d, 0x20, 0xd7, 0x40, 0xf6, 0x7c, 0x15, 0xcd, 0x6c, 0x77, - 0xec, 0xae, 0x3b, 0x02, 0xf1, 0x53, 0xa2, 0xa7, 0x3c, 0xbe, 0x1a, 0x65, 0x2b, 0x56, 0x81, 0x9d, - 0x25, 0x19, 0x57, 0x25, 0x3f, 0xcd, 0x81, 0x72, 0x3e, 0x17, 0x37, 0x1c, 0x86, 0xdd, 0xee, 0xe8, - 0xdd, 0x71, 0xec, 0xdf, 0xcf, 0x0b, 0xc3, 0xc1, 0x59, 0xb8, 0xe1, 0x20, 0x1e, 0x1d, 0x99, 0xed, - 0xc7, 0x40, 0xf8, 0x05, 0x61, 0x38, 0x04, 0x0f, 0x87, 0x10, 0x0e, 0xc3, 0x18, 0x10, 0xff, 0x54, - 0x40, 0x08, 0x1e, 0x02, 0xf1, 0x2e, 0x7f, 0xa2, 0xed, 0xe2, 0x5d, 0xd3, 0x71, 0xf9, 0x61, 0xb0, - 0xc3, 0xa1, 0x7e, 0xf1, 0x8b, 0x61, 0x27, 0x4c, 0x0d, 0xb0, 0x12, 0x4b, 0xc4, 0x37, 0x52, 0xe8, - 0x92, 0x6d, 0x74, 0xc5, 0x7e, 0x49, 0x58, 0xa2, 0x00, 0x1b, 0xa9, 0x5b, 0xc0, 0x43, 0x24, 0x62, - 0x37, 0xc8, 0x42, 0x65, 0x0c, 0xb8, 0x7f, 0xd6, 0x57, 0xb9, 0xba, 0xe0, 0x25, 0x98, 0x01, 0xff, - 0xa7, 0x67, 0xdd, 0xc2, 0x07, 0x63, 0x69, 0xe7, 0x2f, 0xf7, 0xf9, 0x3f, 0x9b, 0x8c, 0x93, 0xd9, - 0x90, 0x7c, 0x9f, 0x3f, 0x85, 0x46, 0x9d, 0xf5, 0x2c, 0x7c, 0xcb, 0x97, 0x78, 0x7b, 0xc3, 0xee, - 0x54, 0x71, 0x85, 0x28, 0x79, 0xd8, 0xe9, 0x19, 0x0d, 0xf6, 0xad, 0x5f, 0xf2, 0xf4, 0x3c, 0xe4, - 0xf3, 0x14, 0x97, 0x21, 0x17, 0x72, 0x78, 0x46, 0x43, 0x7d, 0x1b, 0x87, 0xca, 0x06, 0xfd, 0x9d, - 0xe2, 0x93, 0x90, 0x20, 0xce, 0xcb, 0x68, 0xf6, 0xf7, 0x71, 0x76, 0x4a, 0x5e, 0x7c, 0x1e, 0x52, - 0xc2, 0x69, 0x19, 0xcd, 0xfa, 0xed, 0x9c, 0xd5, 0x63, 0x21, 0xec, 0xc2, 0x61, 0x19, 0xcd, 0xfe, - 0x77, 0x05, 0xbb, 0x60, 0x21, 0xec, 0xe3, 0x8b, 0xf0, 0x5f, 0x7d, 0x67, 0x82, 0x4f, 0x3a, 0x42, - 0x76, 0xcf, 0xc2, 0x24, 0xf7, 0x54, 0x46, 0x73, 0x7f, 0x07, 0x2f, 0x5c, 0x70, 0x14, 0x9f, 0x82, - 0x89, 0x31, 0x05, 0xfe, 0xdd, 0x9c, 0x95, 0xd1, 0x17, 0x2b, 0x90, 0x09, 0x78, 0x27, 0xa3, 0xd9, - 0xbf, 0x87, 0xb3, 0x07, 0xb9, 0x48, 0xd5, 0xb9, 0x77, 0x32, 0x1a, 0xe0, 0xef, 0x89, 0xaa, 0x73, - 0x0e, 0x22, 0x36, 0xe1, 0x98, 0x8c, 0xe6, 0xfe, 0x80, 0x90, 0xba, 0x60, 0x29, 0xbe, 0x08, 0x69, - 0x6f, 0xb2, 0x19, 0xcd, 0xff, 0xbd, 0x9c, 0xdf, 0xe7, 0x21, 0x12, 0x08, 0x4c, 0x76, 0xa3, 0x21, - 0xfe, 0xbe, 0x90, 0x40, 0x80, 0x8b, 0x0c, 0xa3, 0x7e, 0x07, 0x66, 0x34, 0xd2, 0xf7, 0x89, 0x61, - 0xd4, 0xe7, 0xbf, 0x90, 0xde, 0xa4, 0x36, 0x7f, 0x34, 0xc4, 0xf7, 0x8b, 0xde, 0xa4, 0xf4, 0xa4, - 0x1a, 0xfd, 0x1e, 0xc1, 0x68, 0x8c, 0x1f, 0x14, 0xd5, 0xe8, 0x73, 0x08, 0x8a, 0x1b, 0x80, 0x06, - 0xbd, 0x81, 0xd1, 0x78, 0x1f, 0xe4, 0x78, 0xd3, 0x03, 0xce, 0x40, 0xf1, 0xdd, 0x70, 0x22, 0xda, - 0x13, 0x18, 0x8d, 0xfa, 0x43, 0x5f, 0xea, 0x5b, 0xbb, 0x05, 0x1d, 0x81, 0x62, 0xc3, 0x9f, 0x52, - 0x82, 0x5e, 0xc0, 0x68, 0xd8, 0x0f, 0x7d, 0x29, 0x6c, 0xb8, 0x83, 0x4e, 0x40, 0xb1, 0x04, 0xe0, - 0x4f, 0xc0, 0xa3, 0xb1, 0x3e, 0xc2, 0xb1, 0x02, 0x4c, 0x64, 0x68, 0xf0, 0xf9, 0x77, 0x34, 0xff, - 0x5d, 0x31, 0x34, 0x38, 0x07, 0x19, 0x1a, 0x62, 0xea, 0x1d, 0xcd, 0xfd, 0x51, 0x31, 0x34, 0x04, - 0x0b, 0xd1, 0xec, 0xc0, 0xec, 0x36, 0x1a, 0xe1, 0x47, 0x84, 0x66, 0x07, 0xb8, 0x8a, 0x6b, 0x30, - 0x3d, 0x30, 0x21, 0x8e, 0x86, 0xfa, 0x51, 0x0e, 0x25, 0xf7, 0xcf, 0x87, 0xc1, 0xc9, 0x8b, 0x4f, - 0x86, 0xa3, 0xd1, 0x7e, 0xac, 0x6f, 0xf2, 0xe2, 0x73, 0x61, 0xf1, 0x59, 0x48, 0x59, 0xbd, 0x56, - 0x8b, 0x0c, 0x1e, 0x74, 0xf8, 0x69, 0xdf, 0xc2, 0x7f, 0xff, 0x0a, 0x97, 0x8e, 0x60, 0x28, 0x3e, - 0x09, 0x13, 0xb8, 0xbd, 0x8d, 0x9b, 0xa3, 0x38, 0xff, 0xe8, 0x2b, 0xc2, 0x60, 0x12, 0xea, 0xe2, - 0x8b, 0x00, 0x2c, 0x34, 0x42, 0xb7, 0xe1, 0x47, 0xf0, 0x7e, 0xe1, 0x2b, 0xfc, 0x78, 0x9d, 0xcf, - 0xe2, 0x03, 0xb0, 0xc3, 0x7a, 0x87, 0x03, 0x7c, 0x31, 0x0c, 0x40, 0x7b, 0xe4, 0x19, 0x98, 0x7c, - 0xcd, 0xb1, 0x2d, 0x57, 0xdf, 0x1d, 0xc5, 0xfd, 0xc7, 0x9c, 0x5b, 0xd0, 0x13, 0x81, 0xb5, 0xed, - 0x2e, 0x76, 0xf5, 0x5d, 0x67, 0x14, 0xef, 0x9f, 0x70, 0x5e, 0x8f, 0x81, 0x30, 0x1b, 0xba, 0xe3, - 0x8e, 0xd3, 0xee, 0xff, 0x21, 0x98, 0x05, 0x03, 0xa9, 0x34, 0xf9, 0xfb, 0x16, 0x3e, 0x18, 0xc5, - 0xfb, 0xa7, 0xa2, 0xd2, 0x9c, 0xbe, 0xf8, 0x3c, 0xa4, 0xc9, 0x9f, 0xec, 0xcc, 0xec, 0x08, 0xe6, - 0x3f, 0xe3, 0xcc, 0x3e, 0x07, 0x29, 0xd9, 0x71, 0x9b, 0xae, 0x39, 0x5a, 0xd8, 0x7f, 0xce, 0x7b, - 0x5a, 0xd0, 0x17, 0x4b, 0x90, 0x71, 0xdc, 0x66, 0xb3, 0xc7, 0xfd, 0xd3, 0x11, 0xec, 0xff, 0xf3, - 0x2b, 0x5e, 0xc8, 0xc2, 0xe3, 0x21, 0xbd, 0x7d, 0xe7, 0x96, 0xdb, 0xb1, 0xe9, 0x7e, 0xcb, 0x28, - 0x84, 0x2f, 0x71, 0x84, 0x00, 0x4b, 0xb1, 0x02, 0x59, 0xd2, 0x16, 0x71, 0x17, 0x61, 0x14, 0xc4, - 0x97, 0xb9, 0x00, 0x42, 0x4c, 0xe5, 0x6f, 0xfe, 0xb5, 0xcf, 0x9e, 0x91, 0x3e, 0xf3, 0xd9, 0x33, - 0xd2, 0xef, 0x7d, 0xf6, 0x8c, 0xf4, 0x81, 0xcf, 0x9d, 0x39, 0xf6, 0x99, 0xcf, 0x9d, 0x39, 0xf6, - 0xdb, 0x9f, 0x3b, 0x73, 0x2c, 0x3a, 0x4a, 0x0c, 0xd7, 0xed, 0xeb, 0x36, 0x8b, 0x0f, 0xbf, 0xfa, - 0xe0, 0xae, 0xe9, 0xee, 0xf5, 0xb6, 0x17, 0x0d, 0xbb, 0x7d, 0xc9, 0xb0, 0x9d, 0xb6, 0xed, 0x5c, - 0x0a, 0xc7, 0x75, 0xe9, 0x5f, 0xf0, 0xbf, 0x25, 0xb2, 0x66, 0x0e, 0x87, 0x73, 0x75, 0xeb, 0x60, - 0xd8, 0x65, 0xca, 0x6b, 0x10, 0x2f, 0x59, 0x07, 0xe8, 0x14, 0x33, 0x70, 0x5a, 0xaf, 0xdb, 0xe2, - 0x07, 0x37, 0x27, 0xc9, 0xf7, 0x66, 0xb7, 0x85, 0x66, 0xfd, 0xd3, 0xd5, 0xd2, 0x85, 0x2c, 0x3f, - 0x32, 0x5d, 0xfe, 0x1e, 0xe9, 0x68, 0x2d, 0x49, 0x95, 0xac, 0x03, 0xda, 0x90, 0x0d, 0xe9, 0xd5, - 0x47, 0x47, 0xc6, 0xb9, 0x6f, 0x59, 0xf6, 0x1d, 0x8b, 0x54, 0xbb, 0xb3, 0x2d, 0x62, 0xdc, 0x67, - 0xfa, 0x63, 0xdc, 0xef, 0xc6, 0xad, 0xd6, 0x4b, 0x84, 0xae, 0x41, 0x58, 0xb6, 0x93, 0xec, 0x8e, - 0x00, 0x7c, 0x5f, 0x0c, 0xce, 0x0c, 0x84, 0xb3, 0xb9, 0x12, 0x0c, 0x13, 0x42, 0x11, 0x52, 0x4b, - 0x42, 0xb7, 0x0a, 0x30, 0xe9, 0x60, 0xc3, 0xb6, 0x9a, 0x0e, 0x15, 0x44, 0x5c, 0x15, 0x9f, 0x44, - 0x10, 0x96, 0x6e, 0xd9, 0x0e, 0x3f, 0xfa, 0xcc, 0x3e, 0xca, 0x1f, 0x3e, 0xa2, 0x20, 0x72, 0xa2, - 0x24, 0x21, 0x8d, 0xcb, 0x63, 0x4a, 0x43, 0x34, 0x22, 0x14, 0xf9, 0x1f, 0x57, 0x2a, 0x3f, 0x18, - 0x83, 0xf9, 0x7e, 0xa9, 0x90, 0x91, 0xe5, 0xb8, 0x7a, 0xbb, 0x33, 0x4c, 0x2c, 0xcf, 0x42, 0xba, - 0x21, 0x68, 0x8e, 0x2c, 0x97, 0xbb, 0x47, 0x94, 0xcb, 0x94, 0x57, 0x94, 0x10, 0xcc, 0x95, 0x31, - 0x05, 0xe3, 0xb5, 0xe3, 0x9e, 0x24, 0xf3, 0xe1, 0x34, 0x9c, 0x62, 0xc3, 0x49, 0x63, 0x43, 0x89, - 0x7d, 0x70, 0x99, 0x64, 0x83, 0x59, 0xa3, 0xf7, 0x49, 0x94, 0x97, 0x60, 0xa6, 0x46, 0xac, 0x05, - 0x59, 0x05, 0xf9, 0x3b, 0x3c, 0x91, 0xa7, 0xc3, 0x17, 0x42, 0x0e, 0x3f, 0xdf, 0xdf, 0x0a, 0x26, - 0x29, 0xdf, 0x22, 0x81, 0x5c, 0x37, 0xf4, 0x96, 0xde, 0x7d, 0xab, 0x50, 0xe8, 0x29, 0x00, 0x76, - 0xdc, 0xc3, 0xbb, 0xb8, 0x39, 0x75, 0xa5, 0xb0, 0x18, 0x6c, 0xdc, 0x22, 0x2b, 0x89, 0x1e, 0xa1, - 0x4a, 0x53, 0x5a, 0xf2, 0xe7, 0xc5, 0x97, 0x01, 0xfc, 0x0c, 0x74, 0x1a, 0x4e, 0xd6, 0x2b, 0xa5, - 0x95, 0x92, 0x2a, 0x0e, 0x09, 0xd5, 0x37, 0xaa, 0x15, 0x76, 0xcd, 0xea, 0x18, 0x3a, 0x01, 0x28, - 0x98, 0xe9, 0x1d, 0x6a, 0x3a, 0x0e, 0xd3, 0xc1, 0x74, 0x76, 0xe7, 0x25, 0x56, 0xbc, 0x01, 0x79, - 0x76, 0x20, 0x5f, 0xd3, 0x9b, 0x4d, 0xdc, 0xd4, 0x4c, 0x0b, 0x8d, 0x38, 0xdf, 0x5e, 0xf8, 0xf5, - 0xff, 0x32, 0x41, 0x9b, 0x96, 0x63, 0x8c, 0x25, 0xc2, 0x57, 0xb3, 0x88, 0xcf, 0x69, 0xb6, 0x3b, - 0x2d, 0x4c, 0xf7, 0x30, 0x35, 0x53, 0xc8, 0x7f, 0xb4, 0x3b, 0x43, 0xf0, 0xe2, 0x17, 0xd2, 0xea, - 0x8c, 0xcf, 0xee, 0xf5, 0x5e, 0xf1, 0x25, 0x90, 0xc5, 0xc1, 0x51, 0xaf, 0x82, 0x23, 0x11, 0x7f, - 0x83, 0xd7, 0x50, 0x44, 0x33, 0x44, 0x15, 0x57, 0x60, 0x5a, 0x37, 0x0c, 0xdc, 0x09, 0xd5, 0x6f, - 0xc4, 0x0c, 0x22, 0x5a, 0x2b, 0x73, 0x4e, 0xbf, 0x6a, 0x4f, 0x41, 0xd2, 0xa1, 0x9d, 0x32, 0x0a, - 0x42, 0x54, 0x87, 0x93, 0x17, 0xab, 0x30, 0xc5, 0xd4, 0xc0, 0x6b, 0xd1, 0x08, 0x80, 0x7f, 0xcf, - 0x01, 0xb2, 0x94, 0x4d, 0xb4, 0xc6, 0x82, 0x69, 0x76, 0x6b, 0x11, 0x07, 0x5a, 0x73, 0x78, 0x14, - 0xe5, 0x9f, 0x7f, 0xea, 0x71, 0xba, 0x6f, 0x7c, 0x36, 0xac, 0x74, 0x11, 0x83, 0x45, 0x95, 0x39, - 0xb6, 0xdf, 0x5e, 0x0c, 0x53, 0xa2, 0x3c, 0xde, 0xee, 0xc3, 0x0b, 0xfb, 0x17, 0xbc, 0xb0, 0x33, - 0x51, 0x1a, 0x1e, 0x28, 0x29, 0xc7, 0x51, 0x59, 0x46, 0xb1, 0x0c, 0xb9, 0x1d, 0xb3, 0x15, 0xe8, - 0xee, 0xc3, 0x4b, 0xf9, 0x97, 0x9f, 0x7a, 0x9c, 0x0d, 0x34, 0xc2, 0xc4, 0x45, 0x53, 0xae, 0x0e, - 0xb3, 0x7a, 0xaf, 0x3e, 0x32, 0x38, 0x7f, 0xb3, 0xff, 0x1e, 0xa3, 0xe8, 0xcf, 0x06, 0xab, 0xea, - 0x5b, 0xa7, 0x04, 0x4c, 0xeb, 0x6d, 0xd3, 0xb2, 0x2f, 0xd1, 0x7f, 0xb9, 0x55, 0x9a, 0xa0, 0x1f, - 0x63, 0x6c, 0xdb, 0x5e, 0x63, 0xc6, 0x62, 0xb4, 0xde, 0xfe, 0xd9, 0x77, 0xfd, 0xc4, 0x84, 0x6f, - 0x50, 0x8a, 0xab, 0xbe, 0xee, 0x63, 0xcb, 0xb0, 0x9b, 0x63, 0xc5, 0x71, 0xfe, 0x5c, 0x60, 0x88, - 0x08, 0x60, 0x95, 0xb3, 0x16, 0x9f, 0x83, 0x94, 0x07, 0x33, 0xca, 0x77, 0x13, 0x20, 0x1e, 0x07, - 0xf1, 0xdc, 0x98, 0xd2, 0x8e, 0xe3, 0xa7, 0x7f, 0x49, 0xf0, 0x33, 0x1b, 0xb6, 0x46, 0x5a, 0x73, - 0x1d, 0xa6, 0x9a, 0xb6, 0xe5, 0x6a, 0x76, 0xdb, 0x74, 0x71, 0xbb, 0xe3, 0x8e, 0xf4, 0x7c, 0xbf, - 0xcc, 0x40, 0x52, 0x6a, 0x8e, 0xf0, 0xad, 0x0b, 0x36, 0x52, 0x13, 0x76, 0x2f, 0x72, 0x9c, 0x9a, - 0xfc, 0x85, 0x57, 0x13, 0xca, 0x43, 0x6a, 0x72, 0x4f, 0xda, 0xe1, 0x34, 0x6f, 0xf1, 0xe9, 0xce, - 0xdd, 0x67, 0x5a, 0xe0, 0x69, 0xc7, 0xc7, 0xe3, 0x70, 0x86, 0x13, 0x6f, 0xeb, 0x0e, 0xbe, 0x74, - 0xfb, 0xf2, 0x36, 0x76, 0xf5, 0xcb, 0x97, 0x0c, 0xdb, 0x14, 0xbe, 0xce, 0x0c, 0x9f, 0xce, 0x48, - 0xfe, 0x22, 0xcf, 0x9f, 0x8b, 0x3c, 0x10, 0x30, 0x37, 0x7c, 0x1a, 0x9c, 0x1b, 0xd4, 0x41, 0xa5, - 0x05, 0x89, 0x8a, 0x6d, 0x5a, 0x64, 0xf6, 0x6f, 0x62, 0xcb, 0x6e, 0xf3, 0x09, 0x89, 0x7d, 0xa0, - 0x1b, 0x90, 0xd4, 0xdb, 0x76, 0xcf, 0x72, 0xd9, 0x64, 0x54, 0x7e, 0xfc, 0xd7, 0xde, 0x9c, 0x3f, - 0xf6, 0x3b, 0x6f, 0xce, 0x1f, 0x67, 0xb0, 0x4e, 0xf3, 0xd6, 0xa2, 0x69, 0x5f, 0x6a, 0xeb, 0xee, - 0x1e, 0x31, 0x01, 0xbf, 0xf5, 0xe9, 0xc7, 0x80, 0x97, 0x57, 0xb3, 0xdc, 0x4f, 0xfc, 0xe1, 0xcf, - 0x5e, 0x94, 0x54, 0xce, 0x5f, 0x4c, 0x7c, 0xfe, 0x63, 0xf3, 0x92, 0xd2, 0x81, 0xc9, 0x25, 0x6c, - 0x1c, 0x52, 0x60, 0xad, 0xaf, 0xc0, 0xcb, 0xbc, 0xc0, 0xd3, 0x83, 0x05, 0xb2, 0x23, 0x8d, 0x4b, - 0xd8, 0x08, 0x14, 0xbb, 0x84, 0x8d, 0x70, 0x89, 0xe5, 0xa5, 0xdf, 0xfe, 0xfd, 0x33, 0xc7, 0xde, - 0xfb, 0xd9, 0x33, 0xc7, 0x86, 0x76, 0x99, 0x32, 0xba, 0xcb, 0xbc, 0x9e, 0xfa, 0x64, 0x82, 0xf4, - 0x54, 0x1b, 0xbb, 0xdb, 0x3b, 0xee, 0x25, 0xa3, 0x7b, 0xd0, 0x71, 0xed, 0x4b, 0xb7, 0x2f, 0x93, - 0x91, 0x6b, 0xef, 0xf0, 0x9e, 0x42, 0x22, 0x7f, 0x91, 0xe5, 0x2f, 0xde, 0x1e, 0xd2, 0x51, 0xca, - 0x0e, 0x4c, 0x6c, 0x10, 0x46, 0x22, 0x0a, 0xd7, 0x76, 0xf5, 0x16, 0xf7, 0xc8, 0xd8, 0x07, 0x49, - 0x65, 0xf7, 0x76, 0x63, 0x2c, 0xd5, 0x14, 0x57, 0x76, 0x5b, 0x58, 0xdf, 0x61, 0xd7, 0x9f, 0xe2, - 0xd4, 0x95, 0x4f, 0x91, 0x04, 0x7a, 0xd3, 0x69, 0x16, 0x26, 0xf4, 0x1e, 0x3b, 0x54, 0x14, 0x27, - 0x3e, 0x3e, 0xfd, 0x50, 0x56, 0x60, 0x92, 0x9f, 0x2d, 0x40, 0x32, 0xc4, 0x6f, 0xe1, 0x03, 0x5a, - 0x4e, 0x56, 0x25, 0x7f, 0xa2, 0x4b, 0x30, 0x41, 0x6b, 0xcf, 0xef, 0x75, 0x9e, 0x5a, 0x1c, 0xac, - 0xfe, 0x22, 0xad, 0xa5, 0xca, 0xe8, 0x94, 0x9b, 0x90, 0x5a, 0xb2, 0x89, 0x02, 0x85, 0xe1, 0xd2, - 0x0c, 0x8e, 0x56, 0xba, 0xd3, 0xe3, 0xdd, 0xa7, 0xb2, 0x0f, 0x74, 0x02, 0x92, 0xec, 0x3e, 0x1c, - 0x3f, 0x19, 0xc5, 0xbf, 0x94, 0x0a, 0x4c, 0x52, 0xec, 0xf5, 0x8e, 0x77, 0x07, 0x5d, 0x0a, 0xdc, - 0x41, 0xe7, 0xf0, 0x31, 0xbf, 0xb6, 0x08, 0x12, 0x4d, 0xdd, 0xd5, 0x79, 0xc3, 0xe9, 0xdf, 0xca, - 0x8b, 0x90, 0xe2, 0x20, 0x0e, 0x7a, 0x02, 0xe2, 0x76, 0xc7, 0xe1, 0x67, 0x9b, 0x4e, 0x0f, 0x6d, - 0xcb, 0x7a, 0xa7, 0x9c, 0x20, 0x8a, 0xa5, 0x12, 0xea, 0xf2, 0xea, 0x50, 0xd5, 0x78, 0x22, 0xa4, - 0x1a, 0xa2, 0xdb, 0xc5, 0x1f, 0x7a, 0xc7, 0xbc, 0x34, 0xa8, 0x0c, 0x9e, 0xae, 0xfc, 0x2f, 0x09, - 0xee, 0x8f, 0xd0, 0x95, 0x5b, 0xf8, 0xc0, 0x39, 0xb2, 0xaa, 0xbc, 0x0c, 0xe9, 0x0d, 0xfa, 0xba, - 0xcc, 0x4b, 0xf8, 0x00, 0xcd, 0xc1, 0x24, 0x6e, 0x5e, 0x79, 0xf2, 0xc9, 0xcb, 0xcf, 0xb0, 0x8e, - 0xbc, 0x71, 0x4c, 0x15, 0x09, 0xe8, 0x0c, 0xa4, 0x1d, 0x6c, 0x74, 0xae, 0x3c, 0x79, 0xed, 0xd6, - 0x65, 0x26, 0xb8, 0x1b, 0xc7, 0x54, 0x3f, 0xa9, 0x98, 0x22, 0x83, 0xe2, 0xf3, 0x3f, 0x32, 0x2f, - 0x95, 0x27, 0x20, 0xee, 0xf4, 0xda, 0xef, 0x54, 0xe3, 0xff, 0x22, 0x09, 0x67, 0xbd, 0x6c, 0x66, - 0xf6, 0x6e, 0x5f, 0xbe, 0x74, 0x5b, 0x6f, 0x99, 0x4d, 0xdd, 0x7f, 0x13, 0x68, 0xda, 0x13, 0x00, - 0x25, 0x19, 0xda, 0xfe, 0xb9, 0xc3, 0x05, 0xa9, 0x7c, 0x5a, 0x82, 0xec, 0x96, 0xc0, 0xae, 0x63, - 0x17, 0x3d, 0x07, 0xe0, 0x95, 0x25, 0xd4, 0xe1, 0xbe, 0xc5, 0x81, 0xd2, 0x16, 0x3d, 0x26, 0x35, - 0x40, 0x8f, 0x9e, 0x86, 0x54, 0xa7, 0x6b, 0x77, 0x6c, 0x87, 0xdf, 0x8f, 0x1d, 0xc5, 0xeb, 0x51, - 0xa3, 0x47, 0x01, 0xd1, 0xc1, 0xab, 0xdd, 0xb6, 0x5d, 0xd3, 0xda, 0xd5, 0x3a, 0xf6, 0x1d, 0xfe, - 0xec, 0x40, 0x5c, 0x95, 0x69, 0xce, 0x16, 0xcd, 0xd8, 0x20, 0xe9, 0xca, 0xa7, 0x24, 0x48, 0x7b, - 0x28, 0x64, 0x65, 0xa6, 0x37, 0x9b, 0x5d, 0xec, 0x38, 0x7c, 0x7c, 0x8a, 0x4f, 0xf4, 0x1c, 0x4c, - 0x76, 0x7a, 0xdb, 0x9a, 0x18, 0x0b, 0x99, 0x2b, 0xf7, 0x47, 0x6a, 0xb6, 0x50, 0x10, 0xae, 0xdb, - 0xc9, 0x4e, 0x6f, 0x9b, 0xa8, 0xcb, 0x59, 0xc8, 0x46, 0xd4, 0x26, 0x73, 0xdb, 0xaf, 0x08, 0x7d, - 0xd5, 0x88, 0x37, 0x41, 0xeb, 0x74, 0x4d, 0xbb, 0x6b, 0xba, 0x07, 0xf4, 0xe8, 0x5d, 0x5c, 0x95, - 0x45, 0xc6, 0x06, 0x4f, 0x57, 0x5a, 0x90, 0xaf, 0x53, 0x47, 0xdb, 0xaf, 0xfa, 0x35, 0xbf, 0x82, - 0xd2, 0x18, 0x15, 0x1c, 0x5a, 0xb5, 0xd8, 0x40, 0xd5, 0x2e, 0xfe, 0x57, 0x09, 0x32, 0xe5, 0x96, - 0x6d, 0xdc, 0xaa, 0x2d, 0x2d, 0xb7, 0xf4, 0x5d, 0x74, 0x19, 0x8e, 0x97, 0x57, 0xd6, 0x2b, 0x2f, - 0x69, 0xb5, 0x25, 0x6d, 0x79, 0xa5, 0x74, 0xdd, 0x3f, 0xec, 0x3b, 0x77, 0xe2, 0x8d, 0xbb, 0x0b, - 0x28, 0x40, 0xbb, 0x69, 0xd1, 0x85, 0x25, 0xba, 0x04, 0xb3, 0x61, 0x96, 0x52, 0xb9, 0x5e, 0x5d, - 0x6b, 0xc8, 0xd2, 0xdc, 0xf1, 0x37, 0xee, 0x2e, 0x4c, 0x07, 0x38, 0x4a, 0xdb, 0x0e, 0xb6, 0xdc, - 0x41, 0x86, 0xca, 0xfa, 0xea, 0x6a, 0xad, 0x21, 0xc7, 0x06, 0x18, 0x2a, 0x76, 0xbb, 0x6d, 0xba, - 0xe8, 0x61, 0x98, 0x0e, 0x33, 0xac, 0xd5, 0x56, 0xe4, 0xf8, 0x1c, 0x7a, 0xe3, 0xee, 0xc2, 0x54, - 0x80, 0x7a, 0xcd, 0x6c, 0xcd, 0xa5, 0xde, 0xff, 0x63, 0x67, 0x8e, 0x7d, 0xe2, 0x1f, 0x9e, 0x91, - 0xca, 0x2b, 0x43, 0x47, 0xde, 0x95, 0xf1, 0x47, 0x9e, 0x18, 0x5a, 0xde, 0xc0, 0xfb, 0x68, 0x0c, - 0xe6, 0xbd, 0xdc, 0xdb, 0xb8, 0xeb, 0x98, 0xb6, 0x45, 0x46, 0x0b, 0x53, 0x5b, 0xcf, 0x99, 0xe0, - 0x9d, 0xc3, 0x09, 0x86, 0x1b, 0x9e, 0xe7, 0x21, 0x5e, 0xea, 0x74, 0xd0, 0x1c, 0x1d, 0x11, 0xae, - 0x6d, 0xd8, 0x6c, 0x92, 0x4a, 0xa8, 0xde, 0x37, 0xc9, 0x73, 0xec, 0x1d, 0xf7, 0x8e, 0xde, 0xf5, - 0x9e, 0xa9, 0x10, 0xdf, 0xca, 0x33, 0x90, 0xae, 0xd8, 0x96, 0x83, 0x2d, 0xa7, 0x47, 0x03, 0x0c, - 0xdb, 0x44, 0x18, 0x1c, 0x81, 0x7d, 0x10, 0x23, 0xaf, 0x77, 0x3a, 0x94, 0x33, 0xa1, 0x92, 0x3f, - 0xf9, 0xc4, 0xbd, 0x36, 0x54, 0x3c, 0x57, 0xc7, 0x17, 0x8f, 0x2f, 0x00, 0x4f, 0x40, 0xdf, 0x7f, - 0x7f, 0xc0, 0x2c, 0x7b, 0x96, 0x29, 0x28, 0x9e, 0x08, 0xab, 0x34, 0x62, 0xd2, 0x9f, 0x1b, 0x6d, - 0xeb, 0xe6, 0x46, 0xf5, 0xca, 0x10, 0xcb, 0x37, 0x2a, 0xdc, 0xa3, 0x3c, 0x03, 0xb9, 0x0d, 0xbd, - 0xeb, 0xd6, 0xb1, 0x7b, 0x03, 0xeb, 0x4d, 0xdc, 0x0d, 0x7b, 0x13, 0x39, 0xe1, 0x4d, 0x20, 0x48, - 0x50, 0x97, 0x81, 0x4d, 0xa6, 0xf4, 0x6f, 0xc5, 0x84, 0x04, 0x3d, 0x7b, 0xed, 0x79, 0x1a, 0x9c, - 0x83, 0x79, 0x1a, 0xa4, 0xbb, 0x0e, 0x5c, 0xec, 0x88, 0x80, 0x21, 0xfd, 0x40, 0x4f, 0x0a, 0x7f, - 0x21, 0x3e, 0xc2, 0x5f, 0xe0, 0x56, 0x88, 0x7b, 0x0d, 0x6d, 0x98, 0xe4, 0x03, 0xc1, 0xab, 0x89, - 0xe4, 0xd7, 0x04, 0xad, 0x41, 0xbe, 0xa3, 0x77, 0x5d, 0x7a, 0xb5, 0x73, 0x8f, 0x36, 0x83, 0x5b, - 0xba, 0x85, 0x08, 0xc3, 0x1b, 0x6a, 0x2e, 0x2f, 0x26, 0xd7, 0x09, 0x26, 0x2a, 0x9f, 0x4f, 0x40, - 0x92, 0x8b, 0xe3, 0x05, 0x98, 0xe4, 0x02, 0xe7, 0xb6, 0xe9, 0xcc, 0x62, 0x84, 0xfa, 0x2f, 0x7a, - 0x6a, 0xca, 0x01, 0x05, 0x13, 0x7a, 0x08, 0x52, 0xc6, 0x9e, 0x6e, 0x5a, 0x9a, 0xd9, 0xe4, 0x3e, - 0x69, 0xe6, 0xb3, 0x6f, 0xce, 0x4f, 0x56, 0x48, 0x5a, 0x6d, 0x49, 0x9d, 0xa4, 0x99, 0xb5, 0x26, - 0xf1, 0x71, 0xf6, 0xb0, 0xb9, 0xbb, 0xe7, 0x72, 0x03, 0xcb, 0xbf, 0xd0, 0xd3, 0x90, 0x20, 0x5d, - 0xc6, 0xaf, 0xfe, 0xcf, 0x0d, 0x2c, 0x36, 0xbc, 0x78, 0x59, 0x39, 0x45, 0x0a, 0xfe, 0xc0, 0x7f, - 0x9b, 0x97, 0x54, 0xca, 0x81, 0x96, 0x20, 0xd7, 0xd2, 0x1d, 0x57, 0xa3, 0xe3, 0x84, 0x14, 0x3f, - 0xc1, 0x21, 0x06, 0x45, 0xc2, 0x65, 0xcb, 0xeb, 0x9e, 0x21, 0x6c, 0x2c, 0xa9, 0x89, 0x2e, 0x80, - 0x4c, 0x51, 0x0c, 0x6a, 0xaa, 0x98, 0xdf, 0x98, 0xa4, 0xa2, 0x9f, 0x22, 0xe9, 0xcc, 0x82, 0x51, - 0xef, 0xf1, 0x34, 0xa4, 0xe9, 0x6d, 0x63, 0x4a, 0xc2, 0x0e, 0xfd, 0xa7, 0x48, 0x02, 0xcd, 0x3c, - 0x0f, 0x79, 0x7f, 0x86, 0x64, 0x24, 0x29, 0x86, 0xe2, 0x27, 0x53, 0xc2, 0xc7, 0x61, 0xd6, 0xc2, - 0xfb, 0xf4, 0x1a, 0x42, 0x88, 0x3a, 0x4d, 0xa9, 0x11, 0xc9, 0xdb, 0x0a, 0x73, 0x3c, 0x08, 0x53, - 0x86, 0x90, 0x3e, 0xa3, 0x05, 0x4a, 0x9b, 0xf3, 0x52, 0x29, 0xd9, 0x29, 0x48, 0xe9, 0x9d, 0x0e, - 0x23, 0xc8, 0xf0, 0x09, 0xb2, 0xd3, 0xa1, 0x59, 0x17, 0x61, 0x9a, 0xb6, 0xb1, 0x8b, 0x9d, 0x5e, - 0xcb, 0xe5, 0x20, 0x59, 0x4a, 0x93, 0x27, 0x19, 0x2a, 0x4b, 0xa7, 0xb4, 0xe7, 0x20, 0x87, 0x6f, - 0x9b, 0x4d, 0x6c, 0x19, 0x98, 0xd1, 0xe5, 0x28, 0x5d, 0x56, 0x24, 0x52, 0xa2, 0x87, 0xc1, 0x9b, - 0xf7, 0x34, 0x31, 0x29, 0x4f, 0x31, 0x3c, 0x91, 0x5e, 0x62, 0xc9, 0x4a, 0x01, 0x12, 0x4b, 0xba, - 0xab, 0x13, 0x3b, 0xe6, 0xee, 0x33, 0x5f, 0x23, 0xab, 0x92, 0x3f, 0x95, 0x5f, 0x8a, 0x43, 0x62, - 0xcb, 0x76, 0x31, 0xba, 0x1a, 0xf0, 0x6d, 0xa7, 0x22, 0x55, 0xba, 0x6e, 0xee, 0x5a, 0xb8, 0xb9, - 0xea, 0xec, 0x06, 0xde, 0x06, 0xf2, 0x15, 0x2a, 0x16, 0x52, 0xa8, 0x59, 0x98, 0xe8, 0xda, 0x3d, - 0xab, 0x29, 0xce, 0xcb, 0xd3, 0x0f, 0xb4, 0x0c, 0x29, 0x4f, 0x4f, 0x12, 0x23, 0xf5, 0x24, 0x4f, - 0xf4, 0x84, 0xa8, 0x31, 0x4f, 0x50, 0x27, 0xb7, 0xb9, 0xba, 0x94, 0x21, 0xed, 0x59, 0x18, 0x4f, - 0xe1, 0xc6, 0xd1, 0x59, 0x9f, 0x8d, 0xb8, 0x13, 0x5e, 0xef, 0x7b, 0xe2, 0x63, 0x3a, 0x27, 0x7b, - 0x19, 0x5c, 0x7e, 0x21, 0xc5, 0xe2, 0x0f, 0x15, 0x4d, 0xd2, 0x86, 0xf9, 0x8a, 0xc5, 0x1e, 0x2b, - 0xba, 0x0f, 0xd2, 0x8e, 0xb9, 0x6b, 0xe9, 0x6e, 0xaf, 0x8b, 0xb9, 0xee, 0xf9, 0x09, 0x24, 0xd7, - 0xbf, 0x3c, 0xc2, 0x74, 0x2d, 0xf0, 0xe2, 0xdd, 0x25, 0x98, 0xf1, 0xdf, 0x9a, 0xf3, 0x51, 0x98, - 0x9e, 0x21, 0x2f, 0xab, 0x2e, 0x72, 0x94, 0x7f, 0x2d, 0x41, 0x92, 0x4f, 0xee, 0x7e, 0x3f, 0x48, - 0xd1, 0xfd, 0x10, 0x1b, 0xd6, 0x0f, 0xf1, 0xb7, 0xd4, 0x0f, 0xe0, 0xd5, 0xd3, 0xe1, 0xef, 0xd1, - 0x44, 0x79, 0xa1, 0xac, 0x92, 0x75, 0x73, 0x97, 0x8f, 0xfd, 0x00, 0x97, 0xf2, 0xa6, 0x44, 0xa6, - 0x5f, 0x9e, 0x8f, 0xca, 0x90, 0x13, 0x35, 0xd3, 0x76, 0x5a, 0xfa, 0x2e, 0x57, 0xc7, 0x33, 0xc3, - 0xab, 0x47, 0x7c, 0x16, 0x35, 0xc3, 0x6b, 0x44, 0xbd, 0xaf, 0xc8, 0x9e, 0x8d, 0x0d, 0xe9, 0xd9, - 0x90, 0x2a, 0xc5, 0xef, 0x4d, 0x95, 0x42, 0x9d, 0x9e, 0xe8, 0xeb, 0x74, 0xe5, 0x73, 0x12, 0x7f, - 0xec, 0xae, 0xc9, 0x2e, 0xbf, 0xfc, 0x95, 0xf5, 0xd6, 0xd7, 0x73, 0xfd, 0x6a, 0xe2, 0xa6, 0x36, - 0xd0, 0x6d, 0x0f, 0x44, 0x40, 0x86, 0x6b, 0xed, 0x77, 0x1f, 0x12, 0x30, 0x75, 0xbf, 0x1b, 0x7f, - 0x3e, 0x06, 0xd3, 0x03, 0xf4, 0x7f, 0x0d, 0xbb, 0x33, 0x3c, 0x86, 0x27, 0xc6, 0x1c, 0xc3, 0xc9, - 0xa1, 0x63, 0xf8, 0xe7, 0x63, 0x34, 0x32, 0xd0, 0xb1, 0x1d, 0xbd, 0xf5, 0x55, 0xb1, 0xc1, 0xa7, - 0x21, 0xdd, 0xb1, 0x5b, 0x1a, 0xcb, 0x61, 0x37, 0x97, 0x52, 0x1d, 0xbb, 0xa5, 0x0e, 0xa8, 0xda, - 0xc4, 0xdb, 0x65, 0xa0, 0x93, 0x6f, 0x43, 0x37, 0x4c, 0xf6, 0x8f, 0x2a, 0x17, 0xb2, 0x4c, 0x16, - 0xdc, 0x83, 0xba, 0x4c, 0x84, 0x40, 0x7d, 0x32, 0xa9, 0xdf, 0xe7, 0xf3, 0xea, 0xcd, 0x48, 0x55, - 0x4e, 0x48, 0x58, 0x98, 0xbf, 0x31, 0x18, 0x56, 0xea, 0xb3, 0x5c, 0x2a, 0x27, 0x54, 0x3e, 0x28, - 0x01, 0xac, 0x10, 0xe1, 0xd2, 0x16, 0x13, 0xe7, 0xc7, 0xa1, 0x95, 0xd0, 0x42, 0x65, 0xcf, 0x0f, - 0xed, 0x38, 0x5e, 0x83, 0xac, 0x13, 0xac, 0xfa, 0x12, 0xe4, 0x7c, 0x05, 0x77, 0xb0, 0xa8, 0xce, - 0xfc, 0x61, 0xcb, 0xf9, 0x3a, 0x76, 0xd5, 0xec, 0xed, 0xc0, 0x97, 0xf2, 0x6f, 0x24, 0x48, 0xd3, - 0x5a, 0xad, 0x62, 0x57, 0x0f, 0x75, 0xa4, 0xf4, 0x16, 0x3a, 0xf2, 0x7e, 0x00, 0x86, 0xe3, 0x98, - 0xaf, 0x63, 0xae, 0x5f, 0x69, 0x9a, 0x52, 0x37, 0x5f, 0xc7, 0xe8, 0x29, 0x4f, 0xea, 0xf1, 0x11, - 0x52, 0x17, 0xeb, 0x7d, 0x2e, 0xfb, 0x93, 0x30, 0x49, 0x5f, 0x66, 0xdd, 0x77, 0xf8, 0x12, 0x3e, - 0x69, 0xf5, 0xda, 0x8d, 0x7d, 0x47, 0xb9, 0x05, 0x93, 0x8d, 0x7d, 0x16, 0x71, 0x3c, 0x0d, 0xe9, - 0xae, 0x6d, 0x73, 0x6f, 0x90, 0x39, 0xe2, 0x29, 0x92, 0x40, 0x9d, 0x1f, 0x11, 0x64, 0x8b, 0xf9, - 0x41, 0x36, 0x3f, 0x4c, 0x18, 0x1f, 0x2f, 0x4c, 0x48, 0xd6, 0xed, 0xb9, 0xd0, 0x88, 0x42, 0x8f, - 0xc2, 0xc9, 0x7a, 0xed, 0xfa, 0x5a, 0x75, 0x49, 0x5b, 0xad, 0x5f, 0xef, 0x7b, 0x9d, 0x60, 0x2e, - 0xff, 0xc6, 0xdd, 0x85, 0x0c, 0x5f, 0xb0, 0x0f, 0xa3, 0xde, 0x50, 0xab, 0x5b, 0xeb, 0x8d, 0xaa, - 0x2c, 0x31, 0xea, 0x8d, 0x2e, 0xbe, 0x6d, 0xbb, 0xec, 0xed, 0xe3, 0xc7, 0xe1, 0x54, 0x04, 0xb5, - 0xb7, 0x6c, 0x9f, 0x7e, 0xe3, 0xee, 0x42, 0x6e, 0xa3, 0x8b, 0x99, 0xaa, 0x51, 0x8e, 0x45, 0x28, - 0x0c, 0x72, 0xac, 0x6f, 0xac, 0xd7, 0x4b, 0x2b, 0xf2, 0xc2, 0x9c, 0xfc, 0xc6, 0xdd, 0x85, 0xac, - 0xb0, 0x1d, 0x84, 0xfe, 0x9d, 0x5f, 0xb7, 0x27, 0x06, 0xcf, 0x3b, 0xdc, 0xe9, 0xea, 0x9d, 0x0e, - 0xee, 0x3a, 0xc3, 0x36, 0xf6, 0xcf, 0x41, 0x66, 0x29, 0x70, 0x6f, 0xd7, 0x3b, 0xe1, 0x21, 0xd1, - 0x3b, 0xbd, 0xec, 0x43, 0x51, 0x00, 0x96, 0x5b, 0xb6, 0xee, 0x46, 0xd0, 0xc4, 0x02, 0x34, 0x35, - 0xcb, 0xbd, 0x76, 0x35, 0x82, 0x26, 0x2e, 0x68, 0xce, 0x41, 0x66, 0x73, 0x18, 0x51, 0x22, 0x0c, - 0xf4, 0xc4, 0x95, 0x08, 0x9a, 0x89, 0x3e, 0xa0, 0x48, 0xa2, 0x9c, 0x20, 0x3a, 0x0b, 0xe9, 0xb2, - 0x6d, 0xb7, 0x22, 0x48, 0x52, 0x01, 0x9c, 0x7a, 0xe0, 0x4a, 0x72, 0x88, 0x28, 0x1d, 0xa8, 0x50, - 0x99, 0xac, 0x5b, 0x23, 0x68, 0xbc, 0x33, 0x30, 0x47, 0x3e, 0xfa, 0xf1, 0x6e, 0xde, 0x2f, 0x47, - 0x3d, 0xfa, 0x21, 0xfa, 0xf3, 0xde, 0x8e, 0x7e, 0x64, 0x03, 0x5b, 0x0f, 0x5e, 0x94, 0xa1, 0xa3, - 0x77, 0xf5, 0xb6, 0x73, 0xd4, 0x70, 0xea, 0x88, 0x93, 0x35, 0x73, 0x23, 0x34, 0x91, 0xac, 0x6c, - 0xf2, 0xde, 0x82, 0x79, 0x83, 0x56, 0x01, 0x5d, 0x0d, 0x46, 0x77, 0x32, 0xc3, 0xfd, 0x10, 0x46, - 0x2e, 0xa2, 0x3f, 0xcf, 0x43, 0x4a, 0x2c, 0xbc, 0xb8, 0x6d, 0x3e, 0x1b, 0xe5, 0x2d, 0x71, 0x12, - 0xce, 0xeb, 0xb1, 0xa0, 0xaf, 0x83, 0xb4, 0x67, 0xa9, 0xb9, 0x69, 0x52, 0x0e, 0xb3, 0xed, 0x1c, - 0xc0, 0x67, 0x42, 0x45, 0x3f, 0x3c, 0x90, 0x18, 0x1a, 0x71, 0xd8, 0x62, 0x14, 0x9c, 0xdb, 0x0b, - 0x0d, 0x3c, 0x09, 0x09, 0x7d, 0xdb, 0x30, 0xf9, 0x74, 0x7e, 0x7f, 0x04, 0x63, 0xa9, 0x5c, 0xa9, - 0x31, 0x2e, 0xfa, 0x20, 0x07, 0x25, 0x27, 0x95, 0x76, 0x0e, 0x2c, 0x63, 0xaf, 0x6b, 0x5b, 0x07, - 0x7c, 0x06, 0x8f, 0xaa, 0x74, 0x5d, 0xd0, 0x88, 0x4a, 0x7b, 0x4c, 0xa4, 0xd2, 0x3b, 0xd8, 0x9f, - 0xbd, 0xa3, 0x2b, 0xbd, 0xcc, 0x28, 0x44, 0xa5, 0x39, 0x83, 0x52, 0xe3, 0xf1, 0x54, 0xde, 0x6d, - 0xf4, 0x91, 0xaa, 0x7d, 0x8d, 0x45, 0x7a, 0xd8, 0x80, 0x4f, 0xb5, 0xf5, 0x7d, 0x3a, 0x68, 0xc8, - 0x54, 0x42, 0x32, 0x77, 0xf9, 0xc3, 0x25, 0x71, 0x35, 0xd9, 0xd6, 0xf7, 0xaf, 0xeb, 0xce, 0xcd, - 0x44, 0x2a, 0x2e, 0x27, 0x94, 0x4f, 0x12, 0xf7, 0x3b, 0xd4, 0x35, 0xe8, 0x11, 0x40, 0x84, 0x43, - 0xdf, 0xc5, 0x1a, 0x99, 0x84, 0x68, 0x27, 0x0b, 0xdc, 0x7c, 0x5b, 0xdf, 0x2f, 0xed, 0xe2, 0xb5, - 0x5e, 0x9b, 0x56, 0xc0, 0x41, 0xab, 0x20, 0x0b, 0x62, 0xa1, 0x80, 0x9e, 0xbf, 0x30, 0xf0, 0x50, - 0x36, 0x27, 0x60, 0x0e, 0xcd, 0x07, 0x89, 0x43, 0x33, 0xc5, 0xf0, 0xbc, 0x23, 0x5f, 0xa1, 0xa6, - 0xc4, 0xc3, 0x4d, 0x51, 0x5e, 0x84, 0x7c, 0x9f, 0x16, 0x20, 0x05, 0x72, 0x3c, 0x6a, 0x4d, 0x8f, - 0xd3, 0xb0, 0xb5, 0x7b, 0x5a, 0xcd, 0xb0, 0xe0, 0x34, 0x1d, 0x7d, 0xc5, 0xd4, 0x2f, 0x7e, 0x6c, - 0x5e, 0xa2, 0x5b, 0x97, 0x8f, 0x40, 0x2e, 0xa4, 0x06, 0x22, 0x70, 0x29, 0xf9, 0x81, 0x4b, 0x9f, - 0xf8, 0x55, 0xc8, 0x92, 0xa9, 0x14, 0x37, 0x39, 0xed, 0x43, 0x90, 0x67, 0x73, 0x7d, 0xbf, 0xac, - 0x99, 0x0f, 0xbf, 0x2a, 0x04, 0xae, 0x08, 0xa7, 0x3e, 0x2c, 0xf6, 0x8c, 0xa0, 0xba, 0xae, 0x3b, - 0xca, 0x0f, 0x48, 0x90, 0xef, 0xd3, 0x0d, 0xf4, 0x3c, 0xa4, 0x3b, 0x5d, 0x6c, 0x98, 0x81, 0x30, - 0xd7, 0x21, 0x22, 0x4c, 0x50, 0xf1, 0xf9, 0x1c, 0xc4, 0x4d, 0x12, 0xe7, 0x04, 0x9a, 0xb8, 0xa5, - 0x1f, 0x8c, 0xee, 0x05, 0x06, 0x21, 0x7e, 0xb5, 0x60, 0x89, 0x30, 0x29, 0xbf, 0x2a, 0x41, 0x2e, - 0xa4, 0x74, 0xa8, 0x09, 0xf7, 0x93, 0x29, 0x3a, 0x78, 0x36, 0x9d, 0xbf, 0xe6, 0x17, 0x58, 0xa3, - 0x65, 0xae, 0x9c, 0x1e, 0x28, 0xc7, 0x9f, 0x68, 0xa8, 0x73, 0x23, 0xa9, 0x73, 0x04, 0xc7, 0x3f, - 0xa2, 0xce, 0x9e, 0xfd, 0xbb, 0xc1, 0x9c, 0xf1, 0x75, 0x40, 0x9d, 0x6d, 0xb7, 0x1f, 0x3a, 0x36, - 0x2e, 0xb4, 0x4c, 0x98, 0x83, 0x80, 0x4a, 0x1d, 0xc0, 0x1f, 0xb8, 0xa8, 0x34, 0x4e, 0x23, 0xe2, - 0x87, 0xd5, 0xb0, 0x18, 0x2b, 0x48, 0xe5, 0x8d, 0x4f, 0x7c, 0xf6, 0x8c, 0xf4, 0x8e, 0xb8, 0x0e, - 0xbf, 0x5b, 0x87, 0xfb, 0x7c, 0xd2, 0x6d, 0xc3, 0xec, 0x0f, 0x68, 0xcb, 0x9e, 0x71, 0x20, 0xb9, - 0x64, 0x5a, 0x38, 0x7c, 0x3f, 0x6d, 0x64, 0xb8, 0x7b, 0xc4, 0x44, 0x34, 0x4e, 0x38, 0xfc, 0x1e, - 0xa3, 0xdd, 0xff, 0x31, 0x0d, 0x93, 0x2a, 0x7e, 0x4f, 0x0f, 0x3b, 0x2e, 0x7a, 0x02, 0x12, 0xd8, - 0xd8, 0xb3, 0x07, 0xb7, 0x9c, 0x78, 0x2b, 0x17, 0xab, 0xc6, 0x9e, 0xcd, 0x89, 0x6f, 0x1c, 0x53, - 0x29, 0x31, 0xba, 0x06, 0x13, 0x3b, 0xad, 0x1e, 0x0f, 0x84, 0x87, 0xa6, 0x29, 0xc1, 0xb5, 0x4c, - 0xb2, 0x7d, 0x36, 0x46, 0x4e, 0x0a, 0xa3, 0x3f, 0x27, 0x11, 0x1f, 0x56, 0x18, 0xfd, 0x15, 0x09, - 0xbf, 0x30, 0x42, 0x8c, 0x2a, 0x00, 0xa6, 0x65, 0xba, 0x1a, 0x8d, 0x11, 0xf3, 0x69, 0x42, 0x89, - 0x62, 0x35, 0x5d, 0x1a, 0x4f, 0xf6, 0xf9, 0xd3, 0xa6, 0x48, 0x23, 0x35, 0x7e, 0x4f, 0x0f, 0x77, - 0xc5, 0x54, 0x11, 0x51, 0xe3, 0x77, 0x91, 0xec, 0x40, 0x8d, 0x29, 0x39, 0x99, 0x5a, 0xd9, 0x53, - 0xa7, 0xee, 0x3e, 0x7f, 0xc0, 0x7b, 0x61, 0x90, 0x95, 0xbe, 0x74, 0xda, 0xd8, 0xf7, 0x99, 0x27, - 0x0d, 0x96, 0x82, 0x9e, 0xf1, 0x96, 0x70, 0x99, 0xfe, 0x35, 0x93, 0xc7, 0xcc, 0x56, 0x70, 0x1e, - 0x2f, 0x67, 0x40, 0xeb, 0x30, 0xd5, 0x32, 0x1d, 0x57, 0x73, 0x2c, 0xbd, 0xe3, 0xec, 0xd9, 0xae, - 0x43, 0x63, 0xb1, 0x99, 0x2b, 0x0f, 0x0d, 0x42, 0xac, 0x98, 0x8e, 0x5b, 0x17, 0x64, 0x3e, 0x52, - 0xae, 0x15, 0x4c, 0x27, 0x80, 0xf6, 0xce, 0x0e, 0xee, 0x7a, 0x88, 0x34, 0x68, 0x1b, 0x09, 0xb8, - 0x4e, 0xe8, 0x04, 0x67, 0x00, 0xd0, 0x0e, 0xa6, 0xa3, 0x6f, 0x80, 0x99, 0x96, 0xad, 0x37, 0x3d, - 0x3c, 0xcd, 0xd8, 0xeb, 0x59, 0xb7, 0x68, 0x88, 0x37, 0x73, 0xe5, 0x62, 0x44, 0x35, 0x6d, 0xbd, - 0x29, 0x98, 0x2b, 0x84, 0xd4, 0x47, 0x9e, 0x6e, 0xf5, 0xe7, 0x21, 0x0d, 0x66, 0xf5, 0x4e, 0xa7, - 0x75, 0xd0, 0x0f, 0x9f, 0xa7, 0xf0, 0x8f, 0x0c, 0xc2, 0x97, 0x08, 0xf5, 0x10, 0x7c, 0xa4, 0x0f, - 0x64, 0xa2, 0x4d, 0x90, 0x3b, 0x5d, 0x4c, 0xef, 0xad, 0x76, 0xf8, 0x22, 0x85, 0xbe, 0x11, 0x98, - 0xb9, 0x72, 0x61, 0x10, 0x7c, 0x83, 0x51, 0x8a, 0xd5, 0x8c, 0x8f, 0x9c, 0xef, 0x84, 0x73, 0x18, - 0xac, 0x6d, 0x60, 0xfa, 0x86, 0x29, 0x87, 0x9d, 0x1e, 0x0e, 0x4b, 0x29, 0x23, 0x61, 0x43, 0x39, - 0x68, 0x19, 0x32, 0x2c, 0xaa, 0xa5, 0x11, 0x13, 0x49, 0xdf, 0x16, 0xcc, 0x5c, 0x39, 0x17, 0x31, - 0x5c, 0x29, 0xd1, 0x96, 0xed, 0x62, 0x1f, 0x0c, 0xb0, 0x97, 0x88, 0xb6, 0xe1, 0x38, 0x7d, 0x67, - 0xf1, 0x40, 0x0b, 0xdb, 0xe3, 0xc2, 0x0c, 0x45, 0x7c, 0x74, 0x10, 0x91, 0xfe, 0xc8, 0xc0, 0xc1, - 0x56, 0xd0, 0x30, 0xfb, 0xd0, 0x33, 0xb7, 0x07, 0x73, 0x89, 0xa6, 0xed, 0x98, 0x96, 0xde, 0x32, - 0x5f, 0xc7, 0xcc, 0x79, 0xa1, 0x4f, 0x0c, 0x47, 0x6a, 0xda, 0x32, 0xa7, 0xa3, 0xce, 0x4c, 0x40, - 0xd3, 0x76, 0x82, 0xe9, 0xe5, 0x49, 0xbe, 0xe4, 0xf0, 0xde, 0xcc, 0x9c, 0x94, 0x53, 0xec, 0x9d, - 0xcc, 0x9b, 0x89, 0x14, 0xc8, 0x19, 0xe5, 0x3c, 0x64, 0x02, 0x76, 0x0a, 0x15, 0x60, 0x92, 0x4f, - 0xaa, 0xe2, 0x00, 0x3f, 0xff, 0x54, 0xa6, 0x20, 0x1b, 0x34, 0x4d, 0xca, 0x07, 0x24, 0xc8, 0x04, - 0x8c, 0x0e, 0xe1, 0x0c, 0x6e, 0x74, 0xa5, 0x7d, 0x3f, 0xf5, 0x9c, 0xf0, 0x2a, 0x44, 0x3e, 0xdb, - 0x6c, 0xcd, 0xd2, 0x44, 0xee, 0xd4, 0xa0, 0x79, 0xc8, 0x74, 0xae, 0x74, 0x3c, 0x92, 0x38, 0x25, - 0x81, 0xce, 0x95, 0x8e, 0x20, 0x38, 0x0b, 0x59, 0xd2, 0x74, 0x2d, 0xe8, 0x2e, 0xa7, 0xd5, 0x0c, - 0x49, 0xe3, 0x24, 0xca, 0x6f, 0xc6, 0x40, 0xee, 0x37, 0x66, 0xde, 0x06, 0x98, 0x74, 0xe4, 0x0d, - 0xb0, 0x53, 0xfd, 0x5b, 0x6f, 0xfe, 0x6e, 0xdb, 0x2a, 0xc8, 0xfe, 0x9e, 0x11, 0x9b, 0x7b, 0x0e, - 0xf1, 0xff, 0xfb, 0xd6, 0x2a, 0x6a, 0xde, 0xe8, 0x5b, 0xbc, 0x5c, 0x0f, 0x9d, 0x17, 0x49, 0x78, - 0x47, 0x5c, 0xfb, 0xf5, 0x49, 0xd0, 0x6c, 0x76, 0x9a, 0xba, 0x8b, 0x45, 0xc8, 0x3d, 0x70, 0x74, - 0xe4, 0x21, 0xc8, 0xeb, 0x9d, 0x8e, 0xe6, 0xb8, 0xba, 0x8b, 0xb9, 0xa3, 0xc7, 0x02, 0x99, 0x39, - 0xbd, 0xd3, 0xa1, 0xbf, 0x73, 0xc1, 0x1c, 0xbd, 0x07, 0x61, 0x8a, 0x58, 0x78, 0x53, 0x6f, 0x09, - 0x2f, 0x22, 0xc9, 0xfc, 0x41, 0x9e, 0xca, 0x3d, 0x91, 0x26, 0x64, 0x83, 0xc6, 0xdd, 0x0b, 0xcd, - 0x48, 0x81, 0xd0, 0x0c, 0xe2, 0x0f, 0x2f, 0x31, 0x09, 0x89, 0xc7, 0xaa, 0xa2, 0x37, 0x23, 0x67, - 0x69, 0x18, 0xe7, 0x36, 0x8b, 0xbd, 0xa6, 0x54, 0xf6, 0xa1, 0xbc, 0x02, 0x53, 0xe1, 0x79, 0x00, - 0x4d, 0x41, 0xcc, 0xdd, 0xe7, 0xa5, 0xc4, 0xdc, 0x7d, 0x74, 0x39, 0xf0, 0x0b, 0x21, 0x53, 0x51, - 0xb3, 0x1f, 0xe7, 0xf7, 0x43, 0xa7, 0x37, 0x13, 0xa9, 0x98, 0x1c, 0x57, 0xf2, 0x90, 0x0b, 0xcd, - 0x12, 0xca, 0x09, 0x98, 0x8d, 0xb2, 0xf9, 0x8a, 0x09, 0xb3, 0x51, 0xa6, 0x1b, 0x5d, 0x83, 0x94, - 0x67, 0xf4, 0x07, 0xa2, 0x6d, 0xa2, 0x74, 0x8f, 0xc9, 0xa3, 0x0d, 0xed, 0x16, 0xc6, 0x42, 0xbb, - 0x85, 0xca, 0x37, 0x43, 0x61, 0x98, 0x3d, 0xef, 0xdb, 0x3e, 0x48, 0x78, 0x82, 0x3b, 0x01, 0x49, - 0xfe, 0xda, 0x70, 0x8c, 0x86, 0x29, 0xf8, 0x17, 0x11, 0x28, 0xb3, 0xed, 0x71, 0x16, 0xbd, 0xa0, - 0x1f, 0x8a, 0x06, 0xa7, 0x86, 0x9a, 0xf4, 0xe1, 0xbb, 0xed, 0x0c, 0x88, 0xef, 0xb6, 0xd3, 0x0f, - 0xfa, 0x2b, 0x54, 0xd8, 0x12, 0x41, 0xc0, 0xb4, 0xca, 0xbf, 0x94, 0x0f, 0xc5, 0xe1, 0x44, 0xb4, - 0x5d, 0x47, 0x0b, 0x90, 0x25, 0x8b, 0x07, 0x37, 0xbc, 0xce, 0x80, 0xb6, 0xbe, 0xdf, 0xe0, 0x8b, - 0x0c, 0xbe, 0x53, 0x19, 0xf3, 0x76, 0x2a, 0xd1, 0x16, 0x4c, 0xb7, 0x6c, 0x43, 0x6f, 0x69, 0x81, - 0x9d, 0x62, 0x3e, 0x9c, 0x1e, 0x18, 0x66, 0xa7, 0xc5, 0x5e, 0x04, 0x31, 0x41, 0x7c, 0x20, 0xe4, - 0x29, 0xc8, 0x8a, 0xb7, 0xab, 0x8c, 0xaa, 0x90, 0x69, 0x9b, 0xce, 0x36, 0xde, 0xd3, 0x6f, 0x9b, - 0x76, 0x97, 0x8f, 0xab, 0x08, 0xed, 0x59, 0xf5, 0x89, 0xc4, 0x16, 0x76, 0x80, 0x2f, 0xd0, 0x29, - 0x13, 0x91, 0x5b, 0xeb, 0xc9, 0x23, 0x5b, 0x96, 0x61, 0x9b, 0xd4, 0x93, 0x43, 0x37, 0xa9, 0xa3, - 0x76, 0x84, 0x53, 0xd1, 0x3b, 0xc2, 0x6f, 0xd0, 0xce, 0x89, 0x9a, 0x1d, 0x07, 0x37, 0x89, 0x51, - 0x03, 0x66, 0x39, 0x7f, 0x33, 0x24, 0xfd, 0x81, 0x73, 0x67, 0x61, 0xa7, 0x2b, 0x20, 0x75, 0x24, - 0xf8, 0x87, 0x0b, 0x3e, 0x7e, 0x8f, 0x82, 0x17, 0x47, 0x35, 0x12, 0x81, 0xa3, 0x1a, 0xff, 0x8f, - 0x75, 0xc6, 0xfb, 0xe2, 0x62, 0xf3, 0x2c, 0xe0, 0x58, 0x44, 0x9e, 0x41, 0x19, 0xb6, 0xd7, 0x23, - 0x1a, 0x16, 0x3f, 0x72, 0xc3, 0x78, 0x6f, 0x27, 0x46, 0xf7, 0xf6, 0xc4, 0xdb, 0xd9, 0xdb, 0xc9, - 0x7b, 0xec, 0xed, 0x77, 0xb4, 0x1f, 0x3e, 0x22, 0xc1, 0xdc, 0x70, 0x77, 0x2c, 0xb2, 0x43, 0x8e, - 0xb4, 0x3b, 0x39, 0x6c, 0xc6, 0x7b, 0x10, 0xa6, 0xfa, 0xbc, 0x45, 0xa6, 0xcc, 0xb9, 0xd0, 0x72, - 0x5d, 0xf9, 0xf6, 0x38, 0xcc, 0x46, 0x39, 0x74, 0x11, 0x23, 0x56, 0x85, 0x99, 0x26, 0x36, 0xcc, - 0xe6, 0x3d, 0x0f, 0xd8, 0x69, 0xce, 0xfe, 0xff, 0xc7, 0x6b, 0x84, 0x9e, 0xfc, 0x38, 0x40, 0x4a, - 0xc5, 0x4e, 0x87, 0x38, 0x68, 0xec, 0xd7, 0x0e, 0x0d, 0xdc, 0x71, 0xfd, 0xb0, 0x56, 0xe4, 0xba, - 0x81, 0x93, 0x08, 0x3e, 0xb2, 0x7e, 0xf6, 0xf8, 0xd0, 0x55, 0x1e, 0x26, 0x18, 0xba, 0xe0, 0x67, - 0xee, 0xb7, 0xc7, 0xca, 0xe2, 0x04, 0x4f, 0x89, 0x38, 0x41, 0x7c, 0xd8, 0xea, 0x97, 0x3b, 0xe3, - 0x1e, 0x1f, 0x0f, 0x14, 0x5c, 0xe5, 0x81, 0x82, 0xc4, 0xb0, 0xe2, 0x98, 0xcf, 0xee, 0x17, 0x67, - 0xb2, 0x87, 0x4c, 0x83, 0x91, 0x82, 0xe4, 0xb0, 0xa6, 0x06, 0x9c, 0x6b, 0xbf, 0xa9, 0x7e, 0xa8, - 0xe0, 0x29, 0x11, 0x2a, 0x98, 0x1c, 0x56, 0x69, 0xee, 0x4d, 0xfa, 0x95, 0x66, 0xb1, 0x82, 0x17, - 0x02, 0xb1, 0x82, 0x74, 0x7f, 0x18, 0x7e, 0x20, 0x56, 0xe0, 0x71, 0x7b, 0xc1, 0x82, 0xa2, 0x17, - 0x2c, 0xc8, 0x0e, 0x8d, 0x34, 0x70, 0x37, 0xd0, 0x63, 0x16, 0xd1, 0x82, 0x8d, 0x81, 0x68, 0x01, - 0x5b, 0xdc, 0x9f, 0x1f, 0x19, 0x2d, 0xf0, 0xa0, 0xfa, 0xc2, 0x05, 0x1b, 0x03, 0xe1, 0x82, 0xa9, - 0x61, 0x88, 0x7d, 0x3e, 0xa7, 0x8f, 0x18, 0x8e, 0x17, 0x7c, 0x63, 0x74, 0xbc, 0x60, 0xe8, 0x82, - 0x3e, 0xc2, 0xbf, 0xf4, 0xa0, 0x23, 0x02, 0x06, 0xdf, 0x3c, 0x24, 0x60, 0x20, 0x0f, 0x5b, 0xd8, - 0x46, 0x79, 0x97, 0x5e, 0x01, 0x51, 0x11, 0x83, 0xad, 0x88, 0x88, 0x01, 0x5b, 0xda, 0x3f, 0x3c, - 0x46, 0xc4, 0xc0, 0x83, 0x1e, 0x08, 0x19, 0x6c, 0x45, 0x84, 0x0c, 0xd0, 0x70, 0xdc, 0x3e, 0xa7, - 0x28, 0x88, 0x1b, 0x8e, 0x19, 0x5c, 0x0f, 0xc7, 0x0c, 0x66, 0x0e, 0xf7, 0x45, 0xd9, 0xd4, 0xee, - 0xa1, 0x05, 0x83, 0x06, 0xc6, 0xb0, 0xa0, 0x01, 0x5b, 0xd7, 0x3f, 0x36, 0x66, 0xd0, 0xc0, 0xc3, - 0x8e, 0x8c, 0x1a, 0x6c, 0x0c, 0x44, 0x0d, 0x8e, 0x0f, 0x53, 0xb8, 0xbe, 0x49, 0xc6, 0x57, 0xb8, - 0xa1, 0x61, 0x03, 0xf6, 0x23, 0x1b, 0xec, 0xe7, 0x35, 0x40, 0xce, 0xdc, 0x4c, 0xa4, 0x32, 0x72, - 0x56, 0x79, 0x98, 0xb8, 0x35, 0x7d, 0x76, 0x8f, 0x2c, 0x22, 0x70, 0xb7, 0x6b, 0x77, 0xc5, 0x1e, - 0x28, 0xfd, 0x50, 0x2e, 0x40, 0x36, 0x68, 0xe2, 0x0e, 0x09, 0x31, 0xe4, 0x21, 0x17, 0xb2, 0x6a, - 0xca, 0x2f, 0x4a, 0x90, 0x0d, 0xda, 0xab, 0xd0, 0x02, 0x34, 0xcd, 0x17, 0xa0, 0x81, 0xc0, 0x43, - 0x2c, 0x1c, 0x78, 0x98, 0x87, 0x0c, 0x59, 0x84, 0xf5, 0xc5, 0x14, 0xf4, 0x8e, 0x17, 0x53, 0x10, - 0x07, 0x37, 0x59, 0x78, 0x82, 0xcf, 0x53, 0xec, 0xd4, 0x42, 0xde, 0x3b, 0xc4, 0xca, 0xc3, 0xfc, - 0x8f, 0xc1, 0x4c, 0x80, 0xd6, 0x5b, 0xdc, 0xb1, 0xe5, 0xb5, 0xec, 0x51, 0x97, 0xf8, 0x2a, 0xef, - 0x57, 0x25, 0x98, 0x1e, 0x30, 0x97, 0x91, 0x71, 0x03, 0xe9, 0xed, 0x8a, 0x1b, 0xc4, 0xee, 0x3d, - 0x6e, 0x10, 0x5c, 0xae, 0xc6, 0xc3, 0xcb, 0xd5, 0xbf, 0x94, 0x20, 0x17, 0x32, 0xdb, 0xa4, 0x13, - 0x0c, 0xbb, 0x29, 0x76, 0xcc, 0xe9, 0xdf, 0xc4, 0x4f, 0x69, 0xd9, 0xbb, 0x7c, 0x99, 0x48, 0xfe, - 0x24, 0x54, 0xde, 0x44, 0x94, 0xe6, 0xd3, 0x8c, 0xb7, 0xf6, 0x9c, 0x08, 0xde, 0x29, 0xe3, 0xf7, - 0xac, 0x92, 0xfe, 0x3d, 0x2b, 0x6f, 0xa3, 0x7c, 0x32, 0xb0, 0x51, 0x8e, 0x9e, 0x81, 0x34, 0xdd, - 0x05, 0xd0, 0xec, 0x8e, 0xff, 0xc3, 0xcc, 0xc3, 0xef, 0x58, 0x39, 0xf4, 0x92, 0x00, 0xbb, 0x98, - 0xe5, 0x7b, 0x21, 0xe9, 0x90, 0x17, 0x72, 0x1f, 0xa4, 0x49, 0xf5, 0xd9, 0x8f, 0x1b, 0x01, 0x7f, - 0x6a, 0x44, 0x24, 0x28, 0x3f, 0x15, 0x83, 0x7c, 0xdf, 0xac, 0x13, 0xd9, 0xf8, 0xa8, 0x13, 0x2b, - 0xe3, 0x09, 0xe4, 0x0c, 0xc0, 0xae, 0xee, 0x68, 0x77, 0x74, 0xcb, 0xe5, 0xbf, 0x61, 0x1a, 0x57, - 0x03, 0x29, 0x68, 0x0e, 0x52, 0xe4, 0xab, 0xe7, 0xf0, 0x5f, 0x31, 0x8d, 0xab, 0xde, 0x37, 0xaa, - 0x41, 0x12, 0xdf, 0xa6, 0xcf, 0x71, 0xb3, 0x47, 0xed, 0x4f, 0x46, 0x98, 0x27, 0x92, 0x5f, 0x2e, - 0x90, 0xee, 0xfe, 0xa3, 0x37, 0xe7, 0x65, 0x46, 0xfe, 0xa8, 0x77, 0x81, 0x55, 0xe5, 0x00, 0x61, - 0x31, 0xa4, 0xfa, 0xc4, 0x40, 0xc3, 0x85, 0x59, 0xb1, 0xf6, 0x27, 0x42, 0x65, 0x37, 0x71, 0xd4, - 0x5c, 0x1b, 0xb7, 0x3b, 0xb6, 0xdd, 0xd2, 0xd8, 0x38, 0x2f, 0xc1, 0x54, 0x78, 0x92, 0x65, 0xbf, - 0x3c, 0xe8, 0xea, 0xa6, 0xa5, 0x85, 0x7c, 0xe3, 0x2c, 0x4b, 0x64, 0xe3, 0xea, 0x66, 0x22, 0x25, - 0xc9, 0x31, 0x1e, 0xae, 0x79, 0x17, 0x1c, 0x8f, 0x9c, 0x63, 0xd1, 0xd3, 0x90, 0xf6, 0xe7, 0x67, - 0x76, 0x9f, 0xea, 0xb0, 0x38, 0x8c, 0x4f, 0xac, 0x6c, 0xc1, 0xf1, 0xc8, 0x49, 0x16, 0x3d, 0x0f, - 0x49, 0x76, 0x5e, 0x9b, 0x9f, 0xc9, 0x7b, 0x70, 0xf4, 0xec, 0xdc, 0x6b, 0xb9, 0x2a, 0x67, 0x52, - 0x2e, 0xc3, 0xa9, 0xa1, 0xb3, 0xac, 0x1f, 0x4d, 0x91, 0x02, 0xd1, 0x14, 0xe5, 0x67, 0x24, 0x98, - 0x1b, 0x3e, 0x73, 0xa2, 0x72, 0x5f, 0x85, 0x2e, 0x8e, 0x39, 0xef, 0x06, 0x6a, 0x45, 0x96, 0x1b, - 0x5d, 0xbc, 0x83, 0x5d, 0x63, 0x8f, 0x4d, 0xe1, 0xcc, 0x28, 0xe4, 0xd4, 0x1c, 0x4f, 0xa5, 0x3c, - 0x0e, 0x23, 0x7b, 0x0d, 0x1b, 0xae, 0xc6, 0x3a, 0xd5, 0xe1, 0x3f, 0x35, 0x9f, 0x63, 0xa9, 0x75, - 0x96, 0xa8, 0x3c, 0x02, 0x27, 0x87, 0xcc, 0xc5, 0x11, 0xc7, 0xcd, 0x5f, 0x25, 0xc4, 0x91, 0x13, - 0x2c, 0x7a, 0x11, 0x92, 0x8e, 0xab, 0xbb, 0x3d, 0x87, 0xb7, 0xec, 0xfc, 0xc8, 0xb9, 0xb9, 0x4e, - 0xc9, 0x55, 0xce, 0xa6, 0x3c, 0x0b, 0x68, 0x70, 0xa6, 0x8d, 0x58, 0x5b, 0x49, 0x51, 0x6b, 0xab, - 0x6d, 0x38, 0x7d, 0xc8, 0x9c, 0x8a, 0x2a, 0x7d, 0x95, 0x7b, 0x64, 0xac, 0x29, 0xb9, 0xaf, 0x82, - 0x7f, 0x12, 0x83, 0xe3, 0x91, 0x53, 0x6b, 0x60, 0x94, 0x4a, 0x6f, 0x75, 0x94, 0x3e, 0x0f, 0xe0, - 0xee, 0x8b, 0x4b, 0x06, 0xdc, 0xda, 0x47, 0xad, 0x27, 0xf6, 0xb1, 0x41, 0x0d, 0x16, 0x51, 0x8c, - 0xb4, 0xcb, 0xff, 0x22, 0x8b, 0xff, 0xc0, 0x7a, 0xb6, 0x47, 0x67, 0x02, 0x87, 0x2f, 0xf5, 0xc6, - 0x9e, 0x33, 0xfc, 0x85, 0x2f, 0x4b, 0x76, 0xd0, 0xab, 0x70, 0xb2, 0x6f, 0x46, 0xf3, 0xb0, 0x13, - 0x63, 0x4f, 0x6c, 0xc7, 0xc3, 0x13, 0x9b, 0xc0, 0x0e, 0xce, 0x4a, 0x13, 0xe1, 0x59, 0xe9, 0x55, - 0x00, 0x7f, 0x61, 0xeb, 0x9f, 0x87, 0x95, 0x82, 0xe7, 0x61, 0xaf, 0xc1, 0x04, 0xd1, 0x04, 0x21, - 0xaa, 0x08, 0x83, 0x41, 0xba, 0x34, 0xb0, 0x32, 0x66, 0xe4, 0xca, 0x6b, 0x42, 0xdb, 0x82, 0x31, - 0xc6, 0x21, 0x65, 0xbc, 0x10, 0x2e, 0x43, 0x19, 0x1e, 0xae, 0x8c, 0x2e, 0xeb, 0x6f, 0xc1, 0x04, - 0xed, 0xfe, 0xc8, 0x0b, 0xc8, 0xdf, 0x04, 0xa0, 0xbb, 0x6e, 0xd7, 0xdc, 0xee, 0xf9, 0x25, 0x2c, - 0x0c, 0xd1, 0x9f, 0x92, 0x20, 0x2c, 0xdf, 0xc7, 0x15, 0x69, 0xd6, 0xe7, 0x0d, 0x28, 0x53, 0x00, - 0x51, 0x59, 0x83, 0xa9, 0x30, 0x6f, 0xf4, 0x8d, 0x6a, 0xff, 0xdd, 0x26, 0x71, 0xae, 0xcd, 0x9f, - 0xc8, 0xf9, 0x5b, 0x6a, 0xf4, 0x43, 0xf9, 0x96, 0x18, 0x64, 0x83, 0xda, 0xf7, 0x37, 0x70, 0xb2, - 0x54, 0xbe, 0x5d, 0x82, 0x94, 0xd7, 0xfe, 0x43, 0x6e, 0x03, 0xf8, 0x77, 0xeb, 0xbd, 0x18, 0x3c, - 0xdb, 0xf5, 0x88, 0x7b, 0xbb, 0x1e, 0xcf, 0x79, 0x13, 0xc2, 0xd0, 0xc5, 0x7c, 0x50, 0xda, 0xe2, - 0x1c, 0x2e, 0x9f, 0xa0, 0x9e, 0x1d, 0xef, 0x72, 0xef, 0x2c, 0x4c, 0x04, 0xef, 0xe5, 0xb2, 0x0f, - 0x05, 0x07, 0x8e, 0x2b, 0xb1, 0xd1, 0x18, 0xbc, 0x05, 0x2c, 0x1d, 0xfd, 0x16, 0xb0, 0x57, 0x4c, - 0x2c, 0x58, 0xcc, 0x3f, 0x90, 0x20, 0x25, 0xc6, 0x05, 0x7a, 0x31, 0x78, 0x98, 0x4e, 0x9c, 0xcc, - 0x19, 0x6e, 0x97, 0x78, 0x01, 0x81, 0xb3, 0x74, 0x03, 0x57, 0x12, 0xe2, 0x47, 0xbe, 0x92, 0xc0, - 0xfd, 0x90, 0x2f, 0x4b, 0x20, 0xf7, 0x8f, 0xdb, 0xb7, 0x5e, 0xbf, 0xc1, 0xf9, 0x2a, 0x1e, 0x31, - 0x5f, 0x0d, 0xbb, 0x68, 0x90, 0x18, 0x76, 0xd1, 0x60, 0xb0, 0xdd, 0x13, 0xf7, 0xda, 0xee, 0xf7, - 0xc5, 0x20, 0x13, 0x88, 0xf1, 0xa1, 0x27, 0x43, 0xb7, 0x16, 0xce, 0x1e, 0x1a, 0x10, 0x0c, 0x5c, - 0x5b, 0x08, 0x49, 0x2a, 0x76, 0x0f, 0x92, 0x7a, 0xfb, 0x2f, 0x33, 0x46, 0xdf, 0x8c, 0x9f, 0x18, - 0x72, 0x33, 0xfe, 0xef, 0x48, 0x90, 0xf2, 0x82, 0x2f, 0x47, 0xdd, 0x93, 0x3b, 0x01, 0x49, 0xee, - 0x7b, 0xb1, 0x4d, 0x39, 0xfe, 0x15, 0x19, 0x1d, 0x9d, 0x83, 0x94, 0xf8, 0x95, 0x55, 0x3e, 0xc3, - 0x79, 0xdf, 0x17, 0xb7, 0x21, 0x13, 0xd8, 0xd6, 0x44, 0xa7, 0xe0, 0x78, 0xe5, 0x46, 0xb5, 0xf2, - 0x92, 0xd6, 0x78, 0xb9, 0xff, 0xb7, 0xf5, 0x06, 0xb2, 0xd4, 0x2a, 0xfd, 0x96, 0x25, 0x74, 0x12, - 0x66, 0xc2, 0x59, 0x2c, 0x23, 0x36, 0x97, 0x78, 0xff, 0x8f, 0x9d, 0x39, 0x76, 0xf1, 0xcb, 0x12, - 0xcc, 0x44, 0x78, 0xb9, 0xe8, 0x2c, 0xdc, 0xbf, 0xbe, 0xbc, 0x5c, 0x55, 0xb5, 0xfa, 0x5a, 0x69, - 0xa3, 0x7e, 0x63, 0xbd, 0xa1, 0xa9, 0xd5, 0xfa, 0xe6, 0x4a, 0x23, 0x50, 0xe8, 0x02, 0xdc, 0x17, - 0x4d, 0x52, 0xaa, 0x54, 0xaa, 0x1b, 0x0d, 0xf6, 0xe3, 0x7e, 0x43, 0x28, 0xca, 0xeb, 0x6a, 0x43, - 0x8e, 0x0d, 0x87, 0x50, 0xab, 0x37, 0xab, 0x95, 0x86, 0x1c, 0x47, 0xe7, 0xe1, 0xdc, 0x61, 0x14, - 0xda, 0xf2, 0xba, 0xba, 0x5a, 0x6a, 0xc8, 0x89, 0x91, 0x84, 0xf5, 0xea, 0xda, 0x52, 0x55, 0x95, - 0x27, 0x78, 0xbb, 0x3f, 0x16, 0x83, 0xc2, 0x30, 0x67, 0x9a, 0x60, 0x95, 0x36, 0x36, 0x56, 0x5e, - 0xf1, 0xb1, 0x2a, 0x37, 0x36, 0xd7, 0x5e, 0x1a, 0x14, 0xc1, 0x43, 0xa0, 0x1c, 0x46, 0xe8, 0x09, - 0xe2, 0x41, 0x38, 0x7b, 0x28, 0x1d, 0x17, 0xc7, 0x08, 0x32, 0xb5, 0xda, 0x50, 0x5f, 0x91, 0xe3, - 0x68, 0x11, 0x2e, 0x8e, 0x24, 0xf3, 0xf2, 0xe4, 0x04, 0xba, 0x04, 0x8f, 0x1c, 0x4e, 0xcf, 0x04, - 0x24, 0x18, 0x84, 0x88, 0xde, 0x90, 0xe0, 0x78, 0xa4, 0x57, 0x8e, 0xce, 0xc1, 0xfc, 0x86, 0xba, - 0x5e, 0xa9, 0xd6, 0xeb, 0xde, 0x9d, 0x05, 0xad, 0xde, 0x28, 0x35, 0x36, 0xeb, 0x01, 0xd9, 0x28, - 0x70, 0x66, 0x18, 0x91, 0x27, 0x97, 0x43, 0x68, 0xb8, 0x06, 0x08, 0x3d, 0xbd, 0x2b, 0xc1, 0xa9, - 0xa1, 0x5e, 0x38, 0xba, 0x00, 0x0f, 0x6c, 0x55, 0xd5, 0xda, 0xf2, 0x2b, 0xda, 0xd6, 0x7a, 0x23, - 0xf8, 0x2b, 0x92, 0x03, 0xb5, 0x3a, 0x0f, 0xe7, 0x0e, 0xa5, 0xf4, 0xaa, 0x36, 0x8a, 0xb0, 0xaf, - 0x7e, 0xdf, 0x26, 0x41, 0xbe, 0xcf, 0x16, 0xa2, 0xfb, 0xa0, 0xb0, 0x5a, 0xab, 0x97, 0xab, 0x37, - 0x4a, 0x5b, 0xb5, 0x75, 0xb5, 0x7f, 0xcc, 0x9e, 0x83, 0xf9, 0x81, 0xdc, 0xa5, 0xcd, 0x8d, 0x95, - 0x5a, 0xa5, 0xd4, 0xa8, 0x6a, 0xec, 0xa2, 0x09, 0x69, 0xd8, 0x00, 0xd1, 0x4a, 0xed, 0xfa, 0x8d, - 0x86, 0x56, 0x59, 0xa9, 0x55, 0xd7, 0x1a, 0x5a, 0xa9, 0xd1, 0x28, 0xf9, 0xc3, 0xb9, 0xfc, 0xd2, - 0xd0, 0x03, 0x9e, 0x97, 0xc7, 0x3f, 0xe0, 0xc9, 0x8f, 0x70, 0x7a, 0xe7, 0x3b, 0xff, 0xf3, 0x13, - 0xf0, 0x00, 0x7f, 0x98, 0xc8, 0x71, 0xf5, 0x5b, 0xa6, 0xb5, 0xeb, 0xbd, 0x10, 0xc5, 0xbf, 0xf9, - 0x39, 0xcf, 0x13, 0xfc, 0x15, 0x24, 0x91, 0x3a, 0xe2, 0x9d, 0xa8, 0xa1, 0xcf, 0x8b, 0x8e, 0xbc, - 0x1f, 0x30, 0xea, 0x98, 0xe6, 0x61, 0x6f, 0x50, 0x8d, 0x78, 0xe9, 0x2a, 0xe2, 0x8d, 0xaa, 0xb9, - 0xc3, 0xdf, 0x6b, 0x98, 0x3b, 0xf4, 0xf0, 0xab, 0xf2, 0x41, 0x09, 0xa6, 0x6e, 0x98, 0x8e, 0x6b, - 0x77, 0x4d, 0x43, 0x6f, 0x51, 0x47, 0xe2, 0xb9, 0xb1, 0x2f, 0xb4, 0x95, 0xd3, 0x64, 0x1a, 0xe3, - 0x2f, 0x59, 0xed, 0x89, 0x3b, 0x65, 0xc9, 0xdb, 0x7a, 0x8b, 0x5d, 0x26, 0x0b, 0x3e, 0x85, 0xd7, - 0x2f, 0xf6, 0xc0, 0xfc, 0x1a, 0x44, 0x61, 0xbc, 0xc5, 0x58, 0x41, 0x52, 0x7e, 0x20, 0x06, 0x79, - 0xba, 0xc0, 0x71, 0xe8, 0x82, 0x98, 0x2e, 0xb9, 0x6e, 0x42, 0xa2, 0xab, 0xbb, 0x7c, 0x19, 0x52, - 0xbe, 0x76, 0xe4, 0xe7, 0xaf, 0x58, 0x29, 0x14, 0x03, 0xbd, 0x0b, 0x52, 0x6d, 0x7d, 0x5f, 0xa3, - 0x78, 0xb1, 0xb7, 0x84, 0x37, 0xd9, 0xd6, 0xf7, 0x49, 0xfd, 0xd0, 0x37, 0x41, 0x9e, 0x40, 0x1a, - 0x7b, 0xba, 0xb5, 0x8b, 0x19, 0x72, 0xfc, 0x2d, 0x21, 0xe7, 0xda, 0xfa, 0x7e, 0x85, 0xa2, 0x11, - 0x7c, 0xfe, 0x4c, 0xd8, 0xaf, 0x48, 0x7c, 0x75, 0x49, 0x05, 0x83, 0x74, 0x90, 0x0d, 0xef, 0x8b, - 0x16, 0x2a, 0x82, 0xb6, 0xe7, 0x87, 0xc9, 0xbe, 0x4f, 0xac, 0xe5, 0x1c, 0xa9, 0xde, 0x67, 0xde, - 0x9c, 0x97, 0x58, 0xa9, 0x79, 0x63, 0x40, 0xec, 0x19, 0xb6, 0x6a, 0xd6, 0xa8, 0x7f, 0x13, 0x1b, - 0xe9, 0xdf, 0xe4, 0x84, 0x7f, 0xc3, 0x00, 0x81, 0x71, 0x93, 0x7c, 0xde, 0x86, 0x4f, 0x48, 0x90, - 0x59, 0x0a, 0x3c, 0xdd, 0x59, 0x80, 0xc9, 0xb6, 0x6d, 0x99, 0xb7, 0x70, 0xd7, 0x8b, 0xba, 0xb3, - 0x4f, 0xe2, 0x83, 0xb0, 0x5f, 0x80, 0x74, 0x0f, 0xc4, 0x03, 0x2a, 0xe2, 0x9b, 0x70, 0xdd, 0xc1, - 0xdb, 0x8e, 0x29, 0xe4, 0xac, 0x8a, 0x4f, 0xf4, 0x30, 0xc8, 0x0e, 0x36, 0x7a, 0x5d, 0xd3, 0x3d, - 0xd0, 0x0c, 0xdb, 0x72, 0x75, 0xc3, 0xe5, 0x8b, 0xb5, 0xbc, 0x48, 0xaf, 0xb0, 0x64, 0x02, 0xd2, - 0xc4, 0xae, 0x6e, 0xb6, 0xd8, 0x61, 0xb4, 0xb4, 0x2a, 0x3e, 0x79, 0x55, 0xef, 0x4e, 0x06, 0x97, - 0x2a, 0x15, 0x90, 0xed, 0x0e, 0xee, 0x86, 0x76, 0xdd, 0x99, 0x36, 0x16, 0x7e, 0xeb, 0xd3, 0x8f, - 0xcd, 0x72, 0x81, 0xf3, 0xfd, 0x5a, 0x76, 0x03, 0x4b, 0xcd, 0x0b, 0x0e, 0xb1, 0x1d, 0xff, 0x4a, - 0x28, 0xce, 0xde, 0xdb, 0xf6, 0xdf, 0x2e, 0x9a, 0x1d, 0x10, 0x6a, 0xc9, 0x3a, 0x28, 0x17, 0x7e, - 0xc3, 0x87, 0xe6, 0x8b, 0x99, 0x0d, 0xba, 0x70, 0x09, 0xc6, 0xdc, 0x29, 0x0c, 0x71, 0xef, 0x5e, - 0xd3, 0xcd, 0x96, 0xf8, 0xb1, 0x5c, 0x95, 0x7f, 0xa1, 0xa2, 0x17, 0x47, 0x4a, 0x50, 0x6f, 0x59, - 0x19, 0xa6, 0x1b, 0x65, 0xdb, 0x6a, 0x86, 0xc3, 0x47, 0xa8, 0x02, 0x49, 0xd7, 0xbe, 0x85, 0x2d, - 0x2e, 0xa0, 0xf2, 0x23, 0x47, 0x78, 0xe7, 0x4e, 0xe5, 0xac, 0xe8, 0x1b, 0x40, 0x6e, 0xe2, 0x16, - 0xde, 0x65, 0x97, 0x4d, 0xf7, 0xf4, 0x2e, 0x66, 0xaf, 0x1e, 0xdc, 0xd3, 0x2b, 0x76, 0x79, 0x0f, - 0xaa, 0x4e, 0x91, 0xd0, 0x46, 0xf8, 0x71, 0xd8, 0x49, 0x6f, 0x8b, 0x38, 0xb2, 0x8d, 0x01, 0xcd, - 0x0b, 0x5a, 0x9f, 0xd0, 0x63, 0xb2, 0x0f, 0x83, 0xdc, 0xb3, 0xb6, 0x6d, 0x8b, 0xfe, 0xc6, 0x24, - 0xf7, 0xb0, 0x53, 0x6c, 0xef, 0xc5, 0x4b, 0xe7, 0x7b, 0x2f, 0x1b, 0x30, 0xe5, 0x93, 0xd2, 0x11, - 0x92, 0x3e, 0xea, 0x08, 0xc9, 0x79, 0x00, 0x84, 0x04, 0xad, 0x02, 0xf8, 0x63, 0x90, 0x46, 0xfe, - 0x33, 0xc3, 0x7b, 0xcc, 0x1f, 0xcd, 0xc1, 0xc6, 0x04, 0x00, 0x90, 0x05, 0x33, 0x6d, 0xd3, 0xd2, - 0x1c, 0xdc, 0xda, 0xd1, 0xb8, 0xe4, 0x08, 0x6e, 0x86, 0x8a, 0xff, 0x85, 0x23, 0xf4, 0xe6, 0xef, - 0x7c, 0xfa, 0xb1, 0xbc, 0xff, 0xfc, 0xdf, 0xc2, 0xe3, 0x8b, 0x57, 0x9f, 0x52, 0xa7, 0xdb, 0xa6, - 0x55, 0xc7, 0xad, 0x9d, 0x25, 0x0f, 0x18, 0x3d, 0x07, 0xa7, 0x7d, 0x81, 0xd8, 0x96, 0xb6, 0x67, - 0xb7, 0x9a, 0x5a, 0x17, 0xef, 0x68, 0x06, 0x7d, 0xbc, 0x30, 0x4b, 0xc5, 0x78, 0xd2, 0x23, 0x59, - 0xb7, 0x6e, 0xd8, 0xad, 0xa6, 0x8a, 0x77, 0x2a, 0x24, 0x1b, 0x9d, 0x03, 0x5f, 0x1a, 0x9a, 0xd9, - 0x74, 0x0a, 0xb9, 0x85, 0xf8, 0x85, 0x84, 0x9a, 0xf5, 0x12, 0x6b, 0x4d, 0xa7, 0x98, 0x7a, 0xff, - 0xc7, 0xe6, 0x8f, 0x7d, 0xfe, 0x63, 0xf3, 0xc7, 0x94, 0x65, 0xfa, 0xba, 0x19, 0x1f, 0x5a, 0xd8, - 0x41, 0xd7, 0x20, 0xad, 0x8b, 0x0f, 0x76, 0x69, 0xe9, 0x90, 0xa1, 0xe9, 0x93, 0x2a, 0x9f, 0x94, - 0x20, 0xb9, 0xb4, 0xb5, 0xa1, 0x9b, 0x5d, 0x54, 0x85, 0x69, 0x5f, 0x57, 0xc7, 0x1d, 0xe5, 0xbe, - 0x7a, 0x8b, 0x61, 0xbe, 0x36, 0xec, 0x88, 0x4e, 0xba, 0x7c, 0xf6, 0xb7, 0x3e, 0xfd, 0xd8, 0xfd, - 0x1c, 0x66, 0xab, 0xef, 0xb4, 0x8e, 0xc0, 0xeb, 0x3f, 0xc5, 0x13, 0x68, 0xf3, 0x4d, 0x98, 0x64, - 0x55, 0x75, 0xd0, 0x8b, 0x30, 0xd1, 0x21, 0x7f, 0xf0, 0x00, 0xee, 0x99, 0xa1, 0x3a, 0x4f, 0xe9, - 0x83, 0x1a, 0xc2, 0xf8, 0x94, 0xef, 0x8c, 0x01, 0x2c, 0x6d, 0x6d, 0x35, 0xba, 0x66, 0xa7, 0x85, - 0xdd, 0xb7, 0xab, 0xed, 0x9b, 0x70, 0x3c, 0x70, 0xb7, 0xbc, 0x6b, 0x1c, 0xbd, 0xfd, 0x33, 0xfe, - 0x2d, 0xf3, 0xae, 0x11, 0x09, 0xdb, 0x74, 0x5c, 0x0f, 0x36, 0x7e, 0x74, 0xd8, 0x25, 0xc7, 0x1d, - 0x94, 0xec, 0xcb, 0x90, 0xf1, 0x85, 0xe1, 0xa0, 0x1a, 0xa4, 0x5c, 0xfe, 0x37, 0x17, 0xb0, 0x32, - 0x5c, 0xc0, 0x82, 0x2d, 0x28, 0x64, 0x8f, 0x5d, 0xf9, 0x4b, 0x09, 0x20, 0x30, 0x46, 0xbe, 0x36, - 0x75, 0x0c, 0xd5, 0x20, 0xc9, 0x8d, 0x73, 0xfc, 0x9e, 0x9f, 0x18, 0x65, 0x00, 0x01, 0xa1, 0x7e, - 0x77, 0x0c, 0x66, 0x36, 0xc5, 0xe8, 0xfd, 0xda, 0x97, 0xc1, 0x26, 0x4c, 0x62, 0xcb, 0xed, 0x9a, - 0xde, 0x06, 0xc4, 0xe3, 0xc3, 0xfa, 0x3c, 0xa2, 0x51, 0x55, 0xcb, 0xed, 0x1e, 0x04, 0x35, 0x40, - 0x60, 0x05, 0xe4, 0xf1, 0xe1, 0x38, 0x14, 0x86, 0xb1, 0xa2, 0xf3, 0x90, 0x37, 0xba, 0x98, 0x26, - 0x84, 0xef, 0xd0, 0x4d, 0x89, 0x64, 0x3e, 0xed, 0xa8, 0x40, 0x1c, 0x35, 0xa2, 0x5c, 0x84, 0xf4, - 0xde, 0x3c, 0xb3, 0x29, 0x1f, 0x81, 0x4e, 0x3c, 0x0d, 0xc8, 0x8b, 0x93, 0xf7, 0xdb, 0x7a, 0x4b, - 0xb7, 0x0c, 0xe1, 0xc1, 0x1e, 0x69, 0xce, 0x17, 0xa7, 0xf7, 0xcb, 0x0c, 0x02, 0x55, 0x61, 0x52, - 0xa0, 0x25, 0x8e, 0x8e, 0x26, 0x78, 0xd1, 0x59, 0xc8, 0x06, 0x27, 0x06, 0xea, 0x8d, 0x24, 0xd4, - 0x4c, 0x60, 0x5e, 0x18, 0x35, 0xf3, 0x24, 0x0f, 0x9d, 0x79, 0xb8, 0xc3, 0xf7, 0xc3, 0x71, 0x98, - 0x56, 0x71, 0xf3, 0xaf, 0x7f, 0xb7, 0x6c, 0x00, 0xb0, 0xa1, 0x4a, 0x2c, 0x29, 0xef, 0x99, 0x7b, - 0x18, 0xef, 0x69, 0x06, 0xb2, 0xe4, 0xb8, 0x5f, 0xad, 0x1e, 0xfa, 0xdd, 0x18, 0x64, 0x83, 0x3d, - 0xf4, 0x37, 0x72, 0xd2, 0x42, 0x6b, 0xbe, 0x99, 0x62, 0x77, 0x07, 0x1e, 0x1e, 0x66, 0xa6, 0x06, - 0xb4, 0x79, 0x84, 0x7d, 0xfa, 0x42, 0x1c, 0x92, 0xfc, 0x0c, 0xcf, 0xfa, 0x80, 0x6f, 0x3b, 0xf2, - 0x02, 0x75, 0x4e, 0xdc, 0x41, 0x8f, 0x74, 0x6d, 0x1f, 0x84, 0x29, 0xb2, 0x46, 0x0e, 0x1d, 0x0c, - 0x92, 0x2e, 0xe4, 0xe8, 0x52, 0xd7, 0x3f, 0x18, 0x8b, 0xe6, 0x21, 0x43, 0xc8, 0x7c, 0x3b, 0x4c, - 0x68, 0xa0, 0xad, 0xef, 0x57, 0x59, 0x0a, 0xba, 0x0c, 0x68, 0xcf, 0x0b, 0x5c, 0x68, 0xbe, 0x20, - 0xa4, 0x0b, 0x39, 0xfa, 0x9a, 0xc0, 0xb4, 0x9f, 0x2b, 0x58, 0xee, 0x07, 0x20, 0x35, 0xd1, 0xd8, - 0xcb, 0xda, 0xfc, 0xdd, 0x72, 0x92, 0xb2, 0x44, 0x5f, 0xd7, 0xfe, 0x36, 0x89, 0xb9, 0xc9, 0x7d, - 0xab, 0x69, 0xbe, 0x4a, 0x69, 0x8c, 0x31, 0x30, 0xfe, 0xfc, 0xcd, 0xf9, 0xb9, 0x03, 0xbd, 0xdd, - 0x2a, 0x2a, 0x11, 0x38, 0x4a, 0xd4, 0x02, 0x9f, 0x38, 0xcf, 0xe1, 0xd5, 0x38, 0xaa, 0x81, 0x7c, - 0x0b, 0x1f, 0x68, 0x5d, 0xfe, 0xc3, 0xec, 0xda, 0x0e, 0x16, 0xef, 0x18, 0x9c, 0x5a, 0x8c, 0x78, - 0xe7, 0x7c, 0xb1, 0x62, 0x9b, 0x16, 0xdf, 0xa3, 0x98, 0xba, 0x85, 0x0f, 0x54, 0xce, 0xb7, 0x8c, - 0x71, 0xf1, 0x01, 0x32, 0x5a, 0xde, 0xf8, 0xc3, 0x9f, 0xbd, 0x78, 0x3a, 0xf0, 0x66, 0xf7, 0xbe, - 0x17, 0x27, 0x63, 0x5d, 0x4c, 0x1c, 0x5f, 0xe4, 0x4f, 0x42, 0x81, 0xc3, 0x60, 0x10, 0x58, 0x2b, - 0x48, 0x87, 0xaf, 0x41, 0x7c, 0xfe, 0xd0, 0x1a, 0x24, 0x30, 0x44, 0x5f, 0xf0, 0xe7, 0x80, 0xd8, - 0xa8, 0xd6, 0x04, 0xb5, 0x93, 0x33, 0xd1, 0x91, 0x7f, 0x4c, 0xf9, 0x0f, 0x12, 0x9c, 0x1a, 0xd0, - 0x66, 0xaf, 0xca, 0x06, 0xa0, 0x6e, 0x20, 0x93, 0x6a, 0x85, 0xd8, 0x0f, 0xbc, 0xb7, 0xc1, 0x31, - 0xdd, 0x1d, 0x98, 0x08, 0xde, 0x9e, 0xc9, 0x8c, 0x5b, 0xb2, 0x5f, 0x97, 0x60, 0x36, 0x58, 0x01, - 0xaf, 0x29, 0x75, 0xc8, 0x06, 0x8b, 0xe6, 0x8d, 0x78, 0x60, 0x9c, 0x46, 0x04, 0xeb, 0x1f, 0x02, - 0x41, 0x5b, 0xbe, 0xc5, 0x60, 0xd1, 0xb9, 0xcb, 0x63, 0x0b, 0x45, 0x54, 0x2c, 0xd2, 0x72, 0xb0, - 0xbe, 0xf9, 0x82, 0x04, 0x89, 0x0d, 0xdb, 0x6e, 0xa1, 0xf7, 0xc0, 0xb4, 0x65, 0xbb, 0x1a, 0x19, - 0x59, 0xb8, 0xa9, 0xf1, 0xd0, 0x01, 0xb3, 0xc6, 0xd5, 0x43, 0x65, 0xf5, 0x47, 0x6f, 0xce, 0x0f, - 0x72, 0x46, 0xbd, 0x9b, 0x9f, 0xb7, 0x6c, 0xb7, 0x4c, 0x89, 0x1a, 0x2c, 0xba, 0xb0, 0x03, 0xb9, - 0x70, 0x71, 0xcc, 0x62, 0x97, 0x46, 0x15, 0x97, 0x1b, 0x59, 0x54, 0x76, 0x3b, 0x50, 0x0e, 0x7b, - 0x21, 0xfc, 0x4f, 0x49, 0xcf, 0x7d, 0x13, 0xc8, 0x5b, 0xfd, 0xa7, 0x4d, 0x96, 0x61, 0x52, 0x9c, - 0x2e, 0x91, 0xc6, 0x3d, 0xb9, 0x12, 0x94, 0x27, 0x67, 0xa6, 0xe1, 0xcf, 0xcf, 0xc4, 0xe0, 0x54, - 0xc5, 0xb6, 0x1c, 0x1e, 0xe8, 0xe1, 0xa3, 0x9a, 0xc5, 0x6a, 0x0f, 0xd0, 0xc3, 0x43, 0xc2, 0x50, - 0xd9, 0xc1, 0x60, 0xd3, 0x16, 0xe4, 0xc9, 0x14, 0x6b, 0xd8, 0xd6, 0x5b, 0x8c, 0x35, 0xe5, 0xec, - 0x56, 0x93, 0xd7, 0xe8, 0x16, 0x3e, 0x20, 0xb8, 0x16, 0xbe, 0x13, 0xc2, 0x8d, 0xdf, 0x1b, 0xae, - 0x85, 0xef, 0x04, 0x70, 0xfd, 0x0d, 0xcd, 0x44, 0x68, 0x43, 0xf3, 0x1a, 0xc4, 0x89, 0x29, 0x9c, - 0x38, 0x82, 0xf1, 0x20, 0x0c, 0x81, 0x69, 0xad, 0x0e, 0xa7, 0x78, 0xa4, 0xc0, 0x59, 0xdf, 0xa1, - 0x12, 0xc5, 0xb4, 0x41, 0x2f, 0xe1, 0x83, 0x88, 0xb0, 0x41, 0x76, 0xac, 0xb0, 0xc1, 0xc5, 0x5f, - 0x90, 0x00, 0xfc, 0x98, 0x19, 0x7a, 0x14, 0x4e, 0x96, 0xd7, 0xd7, 0x96, 0xfc, 0xbd, 0x9d, 0xc0, - 0x8f, 0x07, 0x89, 0x77, 0xbc, 0x9c, 0x0e, 0x36, 0xcc, 0x1d, 0x13, 0x37, 0xd1, 0x43, 0x30, 0x1b, - 0xa6, 0x26, 0x5f, 0xd5, 0x25, 0x59, 0x9a, 0xcb, 0xbe, 0x71, 0x77, 0x21, 0xc5, 0xd6, 0x08, 0xb8, - 0x89, 0x2e, 0xc0, 0xf1, 0x41, 0xba, 0xda, 0xda, 0x75, 0x39, 0x36, 0x97, 0x7b, 0xe3, 0xee, 0x42, - 0xda, 0x5b, 0x4c, 0x20, 0x05, 0x50, 0x90, 0x92, 0xe3, 0xc5, 0xe7, 0xe0, 0x8d, 0xbb, 0x0b, 0x49, - 0x36, 0x64, 0xf8, 0xa6, 0xd0, 0x37, 0x02, 0xd4, 0xac, 0x9d, 0xae, 0x6e, 0x50, 0xd3, 0x30, 0x07, - 0x27, 0x6a, 0x6b, 0xcb, 0x6a, 0xa9, 0xd2, 0xa8, 0xad, 0xaf, 0xf5, 0xfd, 0xe6, 0x51, 0x38, 0x6f, - 0x69, 0x7d, 0xb3, 0xbc, 0x52, 0xd5, 0xea, 0xb5, 0xeb, 0x6b, 0x6c, 0x07, 0x37, 0x94, 0xf7, 0xee, - 0xb5, 0x46, 0x6d, 0xb5, 0x2a, 0xc7, 0xca, 0xd7, 0x86, 0x6e, 0xf6, 0xdc, 0x17, 0x1a, 0x8c, 0xfe, - 0x74, 0x14, 0xfa, 0x31, 0x89, 0xff, 0x1b, 0x00, 0x00, 0xff, 0xff, 0xdf, 0xae, 0x10, 0xc3, 0x37, - 0xa7, 0x00, 0x00, + // 11876 bytes of a gzipped FileDescriptorSet + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x7d, 0x6b, 0x94, 0x24, 0xd7, + 0x59, 0xd8, 0x56, 0x77, 0x4f, 0x4f, 0xf7, 0xd7, 0xaf, 0x9a, 0x3b, 0xb3, 0xbb, 0xb3, 0xb3, 0xd2, + 0xce, 0x6c, 0xad, 0xa4, 0x5d, 0xad, 0xa4, 0x59, 0xed, 0x4a, 0xbb, 0x92, 0x5a, 0x96, 0x44, 0xf7, + 0x4c, 0xef, 0x6c, 0xaf, 0xe6, 0xe5, 0xea, 0x9e, 0xb5, 0x24, 0x1e, 0x45, 0x4d, 0xf5, 0x9d, 0x99, + 0xd2, 0x76, 0x57, 0xb5, 0xab, 0xaa, 0x77, 0x77, 0x94, 0x73, 0x72, 0x4c, 0xc0, 0x8e, 0x11, 0x8f, + 0x98, 0x40, 0xc0, 0xd8, 0x5e, 0x23, 0x20, 0x60, 0x1b, 0x02, 0x81, 0xd8, 0x10, 0x1c, 0x4e, 0x1e, + 0xe4, 0x24, 0x04, 0xc8, 0x09, 0x71, 0xf8, 0x11, 0x38, 0x9c, 0x83, 0x02, 0x36, 0xe7, 0xe0, 0x60, + 0x43, 0x80, 0x18, 0x0e, 0x27, 0x3e, 0xc9, 0xc9, 0xb9, 0xaf, 0x7a, 0x74, 0x57, 0x4f, 0xf7, 0xac, + 0x24, 0x43, 0x20, 0x7f, 0x76, 0xa7, 0xee, 0xfd, 0xbe, 0xef, 0xde, 0xfb, 0xdd, 0xef, 0x7e, 0xaf, + 0xfb, 0x68, 0xf8, 0xbd, 0xab, 0xb0, 0xb0, 0x6b, 0xdb, 0xbb, 0x6d, 0x7c, 0xa1, 0xeb, 0xd8, 0x9e, + 0xbd, 0xdd, 0xdb, 0xb9, 0xd0, 0xc2, 0xae, 0xe1, 0x98, 0x5d, 0xcf, 0x76, 0x16, 0x69, 0x19, 0x2a, + 0x31, 0x88, 0x45, 0x01, 0xa1, 0xac, 0xc1, 0xd4, 0x55, 0xb3, 0x8d, 0x97, 0x7d, 0xc0, 0x06, 0xf6, + 0xd0, 0xd3, 0x90, 0xda, 0x31, 0xdb, 0x78, 0x56, 0x5a, 0x48, 0x9e, 0xcb, 0x5d, 0x7a, 0x60, 0xb1, + 0x0f, 0x69, 0x31, 0x8a, 0xb1, 0x49, 0x8a, 0x55, 0x8a, 0xa1, 0xfc, 0x9f, 0x14, 0x4c, 0xc7, 0xd4, + 0x22, 0x04, 0x29, 0x4b, 0xef, 0x10, 0x8a, 0xd2, 0xb9, 0xac, 0x4a, 0xff, 0x46, 0xb3, 0x30, 0xd9, + 0xd5, 0x8d, 0x9b, 0xfa, 0x2e, 0x9e, 0x4d, 0xd0, 0x62, 0xf1, 0x89, 0x4e, 0x01, 0xb4, 0x70, 0x17, + 0x5b, 0x2d, 0x6c, 0x19, 0xfb, 0xb3, 0xc9, 0x85, 0xe4, 0xb9, 0xac, 0x1a, 0x2a, 0x41, 0x8f, 0xc0, + 0x54, 0xb7, 0xb7, 0xdd, 0x36, 0x0d, 0x2d, 0x04, 0x06, 0x0b, 0xc9, 0x73, 0x13, 0xaa, 0xcc, 0x2a, + 0x96, 0x03, 0xe0, 0xb3, 0x50, 0xba, 0x8d, 0xf5, 0x9b, 0x61, 0xd0, 0x1c, 0x05, 0x2d, 0x92, 0xe2, + 0x10, 0xe0, 0x12, 0xe4, 0x3b, 0xd8, 0x75, 0xf5, 0x5d, 0xac, 0x79, 0xfb, 0x5d, 0x3c, 0x9b, 0xa2, + 0xa3, 0x5f, 0x18, 0x18, 0x7d, 0xff, 0xc8, 0x73, 0x1c, 0xab, 0xb9, 0xdf, 0xc5, 0xa8, 0x02, 0x59, + 0x6c, 0xf5, 0x3a, 0x8c, 0xc2, 0xc4, 0x10, 0xfe, 0xd5, 0xac, 0x5e, 0xa7, 0x9f, 0x4a, 0x86, 0xa0, + 0x71, 0x12, 0x93, 0x2e, 0x76, 0x6e, 0x99, 0x06, 0x9e, 0x4d, 0x53, 0x02, 0x67, 0x07, 0x08, 0x34, + 0x58, 0x7d, 0x3f, 0x0d, 0x81, 0x87, 0x96, 0x20, 0x8b, 0xef, 0x78, 0xd8, 0x72, 0x4d, 0xdb, 0x9a, + 0x9d, 0xa4, 0x44, 0x1e, 0x8c, 0x99, 0x45, 0xdc, 0x6e, 0xf5, 0x93, 0x08, 0xf0, 0xd0, 0x15, 0x98, + 0xb4, 0xbb, 0x9e, 0x69, 0x5b, 0xee, 0x6c, 0x66, 0x41, 0x3a, 0x97, 0xbb, 0x74, 0x5f, 0xac, 0x20, + 0x6c, 0x30, 0x18, 0x55, 0x00, 0xa3, 0x3a, 0xc8, 0xae, 0xdd, 0x73, 0x0c, 0xac, 0x19, 0x76, 0x0b, + 0x6b, 0xa6, 0xb5, 0x63, 0xcf, 0x66, 0x29, 0x81, 0xf9, 0xc1, 0x81, 0x50, 0xc0, 0x25, 0xbb, 0x85, + 0xeb, 0xd6, 0x8e, 0xad, 0x16, 0xdd, 0xc8, 0x37, 0x3a, 0x06, 0x69, 0x77, 0xdf, 0xf2, 0xf4, 0x3b, + 0xb3, 0x79, 0x2a, 0x21, 0xfc, 0x8b, 0x88, 0x0e, 0x6e, 0x99, 0xa4, 0xb9, 0xd9, 0x02, 0x13, 0x1d, + 0xfe, 0xa9, 0x7c, 0x36, 0x0d, 0xa5, 0x71, 0x84, 0xef, 0x59, 0x98, 0xd8, 0x21, 0xe3, 0x9f, 0x4d, + 0x1c, 0x86, 0x3b, 0x0c, 0x27, 0xca, 0xde, 0xf4, 0x3d, 0xb2, 0xb7, 0x02, 0x39, 0x0b, 0xbb, 0x1e, + 0x6e, 0x31, 0x59, 0x49, 0x8e, 0x29, 0x6d, 0xc0, 0x90, 0x06, 0x85, 0x2d, 0x75, 0x4f, 0xc2, 0xf6, + 0x12, 0x94, 0xfc, 0x2e, 0x69, 0x8e, 0x6e, 0xed, 0x0a, 0xa9, 0xbd, 0x30, 0xaa, 0x27, 0x8b, 0x35, + 0x81, 0xa7, 0x12, 0x34, 0xb5, 0x88, 0x23, 0xdf, 0x68, 0x19, 0xc0, 0xb6, 0xb0, 0xbd, 0xa3, 0xb5, + 0xb0, 0xd1, 0x9e, 0xcd, 0x0c, 0xe1, 0xd2, 0x06, 0x01, 0x19, 0xe0, 0x92, 0xcd, 0x4a, 0x8d, 0x36, + 0x7a, 0x26, 0x10, 0xc2, 0xc9, 0x21, 0x32, 0xb4, 0xc6, 0x96, 0xdf, 0x80, 0x1c, 0x6e, 0x41, 0xd1, + 0xc1, 0x64, 0x45, 0xe0, 0x16, 0x1f, 0x59, 0x96, 0x76, 0x62, 0x71, 0xe4, 0xc8, 0x54, 0x8e, 0xc6, + 0x06, 0x56, 0x70, 0xc2, 0x9f, 0xe8, 0x0c, 0xf8, 0x05, 0x1a, 0x15, 0x2b, 0xa0, 0xfa, 0x29, 0x2f, + 0x0a, 0xd7, 0xf5, 0x0e, 0x9e, 0x7b, 0x0d, 0x8a, 0x51, 0xf6, 0xa0, 0x19, 0x98, 0x70, 0x3d, 0xdd, + 0xf1, 0xa8, 0x14, 0x4e, 0xa8, 0xec, 0x03, 0xc9, 0x90, 0xc4, 0x56, 0x8b, 0xea, 0xbf, 0x09, 0x95, + 0xfc, 0x89, 0xbe, 0x2e, 0x18, 0x70, 0x92, 0x0e, 0xf8, 0xa1, 0xc1, 0x19, 0x8d, 0x50, 0xee, 0x1f, + 0xf7, 0xdc, 0x53, 0x50, 0x88, 0x0c, 0x60, 0xdc, 0xa6, 0x95, 0x9f, 0x4a, 0xc1, 0xd1, 0x58, 0xda, + 0xe8, 0x25, 0x98, 0xe9, 0x59, 0xa6, 0xe5, 0x61, 0xa7, 0xeb, 0x60, 0x22, 0xb2, 0xac, 0xad, 0xd9, + 0x3f, 0x98, 0x1c, 0x22, 0x74, 0x5b, 0x61, 0x68, 0x46, 0x45, 0x9d, 0xee, 0x0d, 0x16, 0xa2, 0x97, + 0x21, 0x47, 0xe4, 0x43, 0x77, 0x74, 0x4a, 0x90, 0xad, 0xc6, 0x4b, 0xe3, 0x0d, 0x79, 0x71, 0x39, + 0xc0, 0xac, 0x26, 0x3f, 0x28, 0x25, 0xd4, 0x30, 0x2d, 0xb4, 0x07, 0xf9, 0x5b, 0xd8, 0x31, 0x77, + 0x4c, 0x83, 0xd1, 0x26, 0xec, 0x2c, 0x5e, 0x7a, 0x7a, 0x4c, 0xda, 0x37, 0x42, 0xa8, 0x0d, 0x4f, + 0xf7, 0x70, 0x19, 0xb6, 0xd6, 0x6f, 0xd4, 0xd4, 0xfa, 0xd5, 0x7a, 0x6d, 0x59, 0x8d, 0x50, 0x9e, + 0xfb, 0xb4, 0x04, 0xb9, 0x50, 0x5f, 0x88, 0xda, 0xb2, 0x7a, 0x9d, 0x6d, 0xec, 0x70, 0x8e, 0xf3, + 0x2f, 0x74, 0x12, 0xb2, 0x3b, 0xbd, 0x76, 0x9b, 0x89, 0x0d, 0xb3, 0x79, 0x19, 0x52, 0x40, 0x44, + 0x86, 0x68, 0x29, 0xae, 0x08, 0xa8, 0x96, 0x22, 0x7f, 0xa3, 0x33, 0x90, 0x33, 0x5d, 0xcd, 0xc1, + 0x5d, 0xac, 0x7b, 0xb8, 0x35, 0x9b, 0x5a, 0x90, 0xce, 0x65, 0xaa, 0x89, 0x59, 0x49, 0x05, 0xd3, + 0x55, 0x79, 0x29, 0x9a, 0x83, 0x8c, 0x90, 0xbd, 0xd9, 0x09, 0x02, 0xa1, 0xfa, 0xdf, 0xac, 0x8e, + 0x63, 0xa7, 0x45, 0x1d, 0xfb, 0x56, 0x9e, 0x84, 0xa9, 0x81, 0x41, 0xa2, 0x12, 0xe4, 0x96, 0x6b, + 0x4b, 0xab, 0x15, 0xb5, 0xd2, 0xac, 0x6f, 0xac, 0xcb, 0x47, 0x50, 0x11, 0x42, 0xe3, 0x96, 0xa5, + 0xf3, 0xd9, 0xcc, 0x17, 0x27, 0xe5, 0xf7, 0xbd, 0xef, 0x7d, 0xef, 0x4b, 0x28, 0xbf, 0x94, 0x86, + 0x99, 0x38, 0x2d, 0x17, 0xab, 0x70, 0x03, 0x9e, 0x24, 0x23, 0x3c, 0xa9, 0xc0, 0x44, 0x5b, 0xdf, + 0xc6, 0x6d, 0x3a, 0xb8, 0xe2, 0xa5, 0x47, 0xc6, 0xd2, 0xa3, 0x8b, 0xab, 0x04, 0x45, 0x65, 0x98, + 0xe8, 0x79, 0xce, 0xb9, 0x09, 0x4a, 0xe1, 0xfc, 0x78, 0x14, 0x88, 0xf6, 0xe3, 0x5c, 0x3e, 0x09, + 0x59, 0xf2, 0x3f, 0x9b, 0x96, 0x34, 0x9b, 0x16, 0x52, 0x40, 0xa7, 0x65, 0x0e, 0x32, 0x54, 0xb1, + 0xb5, 0xb0, 0x3f, 0x65, 0xe2, 0x9b, 0xa8, 0x82, 0x16, 0xde, 0xd1, 0x7b, 0x6d, 0x4f, 0xbb, 0xa5, + 0xb7, 0x7b, 0x98, 0xaa, 0xa8, 0xac, 0x9a, 0xe7, 0x85, 0x37, 0x48, 0x19, 0x9a, 0x87, 0x1c, 0xd3, + 0x83, 0xa6, 0xd5, 0xc2, 0x77, 0xa8, 0x25, 0x9c, 0x50, 0x99, 0x6a, 0xac, 0x93, 0x12, 0xd2, 0xfc, + 0xab, 0xae, 0x6d, 0x09, 0x65, 0x42, 0x9b, 0x20, 0x05, 0xb4, 0xf9, 0xa7, 0xfa, 0x8d, 0xf0, 0xfd, + 0xf1, 0xc3, 0x1b, 0xd0, 0x7e, 0x67, 0xa1, 0x44, 0x21, 0x9e, 0xe0, 0x6b, 0x55, 0x6f, 0xcf, 0x4e, + 0x51, 0x01, 0x28, 0xb2, 0xe2, 0x0d, 0x5e, 0xaa, 0xfc, 0x7c, 0x02, 0x52, 0xd4, 0x14, 0x94, 0x20, + 0xd7, 0x7c, 0x79, 0xb3, 0xa6, 0x2d, 0x6f, 0x6c, 0x55, 0x57, 0x6b, 0xb2, 0x44, 0xa6, 0x9e, 0x16, + 0x5c, 0x5d, 0xdd, 0xa8, 0x34, 0xe5, 0x84, 0xff, 0x5d, 0x5f, 0x6f, 0x5e, 0x79, 0x52, 0x4e, 0xfa, + 0x08, 0x5b, 0xac, 0x20, 0x15, 0x06, 0x78, 0xe2, 0x92, 0x3c, 0x81, 0x64, 0xc8, 0x33, 0x02, 0xf5, + 0x97, 0x6a, 0xcb, 0x57, 0x9e, 0x94, 0xd3, 0xd1, 0x92, 0x27, 0x2e, 0xc9, 0x93, 0xa8, 0x00, 0x59, + 0x5a, 0x52, 0xdd, 0xd8, 0x58, 0x95, 0x33, 0x3e, 0xcd, 0x46, 0x53, 0xad, 0xaf, 0xaf, 0xc8, 0x59, + 0x9f, 0xe6, 0x8a, 0xba, 0xb1, 0xb5, 0x29, 0x83, 0x4f, 0x61, 0xad, 0xd6, 0x68, 0x54, 0x56, 0x6a, + 0x72, 0xce, 0x87, 0xa8, 0xbe, 0xdc, 0xac, 0x35, 0xe4, 0x7c, 0xa4, 0x5b, 0x4f, 0x5c, 0x92, 0x0b, + 0x7e, 0x13, 0xb5, 0xf5, 0xad, 0x35, 0xb9, 0x88, 0xa6, 0xa0, 0xc0, 0x9a, 0x10, 0x9d, 0x28, 0xf5, + 0x15, 0x5d, 0x79, 0x52, 0x96, 0x83, 0x8e, 0x30, 0x2a, 0x53, 0x91, 0x82, 0x2b, 0x4f, 0xca, 0x48, + 0x59, 0x82, 0x09, 0x2a, 0x86, 0x08, 0x41, 0x71, 0xb5, 0x52, 0xad, 0xad, 0x6a, 0x1b, 0x9b, 0x64, + 0xd1, 0x54, 0x56, 0x65, 0x29, 0x28, 0x53, 0x6b, 0xef, 0xde, 0xaa, 0xab, 0xb5, 0x65, 0x39, 0x11, + 0x2e, 0xdb, 0xac, 0x55, 0x9a, 0xb5, 0x65, 0x39, 0xa9, 0x18, 0x30, 0x13, 0x67, 0x02, 0x63, 0x97, + 0x50, 0x48, 0x16, 0x12, 0x43, 0x64, 0x81, 0xd2, 0xea, 0x97, 0x05, 0xe5, 0x0b, 0x09, 0x98, 0x8e, + 0x71, 0x03, 0x62, 0x1b, 0x79, 0x01, 0x26, 0x98, 0x2c, 0x33, 0x55, 0xfc, 0x70, 0xac, 0x3f, 0x41, + 0x25, 0x7b, 0xc0, 0x39, 0xa2, 0x78, 0x61, 0xb7, 0x31, 0x39, 0xc4, 0x6d, 0x24, 0x24, 0x06, 0x04, + 0xf6, 0x1b, 0x07, 0xcc, 0x35, 0xf3, 0x68, 0xae, 0x8c, 0xe3, 0xd1, 0xd0, 0xb2, 0xc3, 0x99, 0xed, + 0x89, 0x18, 0xb3, 0xfd, 0x2c, 0x4c, 0x0d, 0x10, 0x1a, 0xdb, 0x7c, 0x7e, 0xab, 0x04, 0xb3, 0xc3, + 0x98, 0x33, 0x42, 0x25, 0x26, 0x22, 0x2a, 0xf1, 0xd9, 0x7e, 0x0e, 0x9e, 0x1e, 0x3e, 0x09, 0x03, + 0x73, 0xfd, 0x09, 0x09, 0x8e, 0xc5, 0x87, 0x07, 0xb1, 0x7d, 0x78, 0x1e, 0xd2, 0x1d, 0xec, 0xed, + 0xd9, 0xc2, 0x11, 0x7e, 0x28, 0xc6, 0xbd, 0x22, 0xd5, 0xfd, 0x93, 0xcd, 0xb1, 0xc2, 0xfe, 0x59, + 0x72, 0x98, 0x8f, 0xcf, 0x7a, 0x33, 0xd0, 0xd3, 0x6f, 0x4f, 0xc0, 0xd1, 0x58, 0xe2, 0xb1, 0x1d, + 0xbd, 0x1f, 0xc0, 0xb4, 0xba, 0x3d, 0x8f, 0x39, 0xbb, 0x4c, 0x13, 0x67, 0x69, 0x09, 0x55, 0x5e, + 0x44, 0xcb, 0xf6, 0x3c, 0xbf, 0x9e, 0x19, 0x51, 0x60, 0x45, 0x14, 0xe0, 0xe9, 0xa0, 0xa3, 0x29, + 0xda, 0xd1, 0x53, 0x43, 0x46, 0x3a, 0x20, 0x98, 0x8f, 0x83, 0x6c, 0xb4, 0x4d, 0x6c, 0x79, 0x9a, + 0xeb, 0x39, 0x58, 0xef, 0x98, 0xd6, 0x2e, 0xb3, 0xb3, 0xe5, 0x89, 0x1d, 0xbd, 0xed, 0x62, 0xb5, + 0xc4, 0xaa, 0x1b, 0xa2, 0x96, 0x60, 0x50, 0x01, 0x72, 0x42, 0x18, 0xe9, 0x08, 0x06, 0xab, 0xf6, + 0x31, 0x94, 0xef, 0xc9, 0x42, 0x2e, 0x14, 0x4c, 0xa1, 0xd3, 0x90, 0x7f, 0x55, 0xbf, 0xa5, 0x6b, + 0x22, 0x40, 0x66, 0x9c, 0xc8, 0x91, 0xb2, 0x4d, 0x1e, 0x24, 0x3f, 0x0e, 0x33, 0x14, 0xc4, 0xee, + 0x79, 0xd8, 0xd1, 0x8c, 0xb6, 0xee, 0xba, 0x94, 0x69, 0x19, 0x0a, 0x8a, 0x48, 0xdd, 0x06, 0xa9, + 0x5a, 0x12, 0x35, 0xe8, 0x32, 0x4c, 0x53, 0x8c, 0x4e, 0xaf, 0xed, 0x99, 0xdd, 0x36, 0xd6, 0x48, + 0xc8, 0xee, 0x52, 0x93, 0xe3, 0xf7, 0x6c, 0x8a, 0x40, 0xac, 0x71, 0x00, 0xd2, 0x23, 0x17, 0x2d, + 0xc3, 0xfd, 0x14, 0x6d, 0x17, 0x5b, 0xd8, 0xd1, 0x3d, 0xac, 0xe1, 0xf7, 0xf6, 0xf4, 0xb6, 0xab, + 0xe9, 0x56, 0x4b, 0xdb, 0xd3, 0xdd, 0xbd, 0xd9, 0x19, 0xdf, 0x2d, 0x39, 0x41, 0x00, 0x57, 0x38, + 0x5c, 0x8d, 0x82, 0x55, 0xac, 0xd6, 0x35, 0xdd, 0xdd, 0x43, 0x65, 0x38, 0x46, 0xa9, 0xb8, 0x9e, + 0x63, 0x5a, 0xbb, 0x9a, 0xb1, 0x87, 0x8d, 0x9b, 0x5a, 0xcf, 0xdb, 0x79, 0x7a, 0xf6, 0x64, 0xb8, + 0x7d, 0xda, 0xc3, 0x06, 0x85, 0x59, 0x22, 0x20, 0x5b, 0xde, 0xce, 0xd3, 0xa8, 0x01, 0x79, 0x32, + 0x19, 0x1d, 0xf3, 0x35, 0xac, 0xed, 0xd8, 0x0e, 0xb5, 0xa1, 0xc5, 0x18, 0xd5, 0x14, 0xe2, 0xe0, + 0xe2, 0x06, 0x47, 0x58, 0xb3, 0x5b, 0xb8, 0x3c, 0xd1, 0xd8, 0xac, 0xd5, 0x96, 0xd5, 0x9c, 0xa0, + 0x72, 0xd5, 0x76, 0x88, 0x40, 0xed, 0xda, 0x3e, 0x83, 0x73, 0x4c, 0xa0, 0x76, 0x6d, 0xc1, 0xde, + 0xcb, 0x30, 0x6d, 0x18, 0x6c, 0xcc, 0xa6, 0xa1, 0xf1, 0xc0, 0xda, 0x9d, 0x95, 0x23, 0xcc, 0x32, + 0x8c, 0x15, 0x06, 0xc0, 0x65, 0xdc, 0x45, 0xcf, 0xc0, 0xd1, 0x80, 0x59, 0x61, 0xc4, 0xa9, 0x81, + 0x51, 0xf6, 0xa3, 0x5e, 0x86, 0xe9, 0xee, 0xfe, 0x20, 0x22, 0x8a, 0xb4, 0xd8, 0xdd, 0xef, 0x47, + 0x7b, 0x0a, 0x66, 0xba, 0x7b, 0xdd, 0x41, 0xbc, 0xf3, 0x61, 0x3c, 0xd4, 0xdd, 0xeb, 0xf6, 0x23, + 0x3e, 0x48, 0xb3, 0x2c, 0x0e, 0x36, 0xa8, 0x77, 0x78, 0x3c, 0x0c, 0x1e, 0xaa, 0x40, 0x8b, 0x20, + 0x1b, 0x86, 0x86, 0x2d, 0x7d, 0xbb, 0x8d, 0x35, 0xdd, 0xc1, 0x96, 0xee, 0xce, 0xce, 0x53, 0xe0, + 0x94, 0xe7, 0xf4, 0xb0, 0x5a, 0x34, 0x8c, 0x1a, 0xad, 0xac, 0xd0, 0x3a, 0x74, 0x1e, 0xa6, 0xec, + 0xed, 0x57, 0x0d, 0x26, 0x91, 0x5a, 0xd7, 0xc1, 0x3b, 0xe6, 0x9d, 0xd9, 0x07, 0x28, 0x7b, 0x4b, + 0xa4, 0x82, 0xca, 0xe3, 0x26, 0x2d, 0x46, 0x0f, 0x83, 0x6c, 0xb8, 0x7b, 0xba, 0xd3, 0xa5, 0x2a, + 0xd9, 0xed, 0xea, 0x06, 0x9e, 0x7d, 0x90, 0x81, 0xb2, 0xf2, 0x75, 0x51, 0x4c, 0x56, 0x84, 0x7b, + 0xdb, 0xdc, 0xf1, 0x04, 0xc5, 0xb3, 0x6c, 0x45, 0xd0, 0x32, 0x4e, 0xed, 0x1c, 0xc8, 0x84, 0x13, + 0x91, 0x86, 0xcf, 0x51, 0xb0, 0x62, 0x77, 0xaf, 0x1b, 0x6e, 0xf7, 0x0c, 0x14, 0x08, 0x64, 0xd0, + 0xe8, 0xc3, 0xcc, 0x71, 0xeb, 0xee, 0x85, 0x5a, 0x7c, 0x12, 0x8e, 0x11, 0xa0, 0x0e, 0xf6, 0xf4, + 0x96, 0xee, 0xe9, 0x21, 0xe8, 0x47, 0x29, 0x34, 0x61, 0xfb, 0x1a, 0xaf, 0x8c, 0xf4, 0xd3, 0xe9, + 0x6d, 0xef, 0xfb, 0x82, 0xf5, 0x18, 0xeb, 0x27, 0x29, 0x13, 0xa2, 0xf5, 0x8e, 0x45, 0x53, 0x4a, + 0x19, 0xf2, 0x61, 0xb9, 0x47, 0x59, 0x60, 0x92, 0x2f, 0x4b, 0xc4, 0x09, 0x5a, 0xda, 0x58, 0x26, + 0xee, 0xcb, 0x2b, 0x35, 0x39, 0x41, 0xdc, 0xa8, 0xd5, 0x7a, 0xb3, 0xa6, 0xa9, 0x5b, 0xeb, 0xcd, + 0xfa, 0x5a, 0x4d, 0x4e, 0x86, 0x1c, 0xfb, 0xeb, 0xa9, 0xcc, 0x43, 0xf2, 0x59, 0xe5, 0x17, 0x93, + 0x50, 0x8c, 0xc6, 0xd6, 0xe8, 0x5d, 0x70, 0x5c, 0xa4, 0xc8, 0x5c, 0xec, 0x69, 0xb7, 0x4d, 0x87, + 0x2e, 0xc8, 0x8e, 0xce, 0x8c, 0xa3, 0x2f, 0x3f, 0x33, 0x1c, 0xaa, 0x81, 0xbd, 0xf7, 0x98, 0x0e, + 0x59, 0x6e, 0x1d, 0xdd, 0x43, 0xab, 0x30, 0x6f, 0xd9, 0x9a, 0xeb, 0xe9, 0x56, 0x4b, 0x77, 0x5a, + 0x5a, 0x90, 0x9c, 0xd4, 0x74, 0xc3, 0xc0, 0xae, 0x6b, 0x33, 0x43, 0xe8, 0x53, 0xb9, 0xcf, 0xb2, + 0x1b, 0x1c, 0x38, 0xb0, 0x10, 0x15, 0x0e, 0xda, 0x27, 0xbe, 0xc9, 0x61, 0xe2, 0x7b, 0x12, 0xb2, + 0x1d, 0xbd, 0xab, 0x61, 0xcb, 0x73, 0xf6, 0xa9, 0x7f, 0x9e, 0x51, 0x33, 0x1d, 0xbd, 0x5b, 0x23, + 0xdf, 0xe8, 0x06, 0x3c, 0x14, 0x80, 0x6a, 0x6d, 0xbc, 0xab, 0x1b, 0xfb, 0x1a, 0x75, 0xc6, 0x69, + 0xa2, 0x47, 0x33, 0x6c, 0x6b, 0xa7, 0x6d, 0x1a, 0x9e, 0x4b, 0xf5, 0x03, 0xd3, 0x71, 0x4a, 0x80, + 0xb1, 0x4a, 0x11, 0xae, 0xbb, 0xb6, 0x45, 0x7d, 0xf0, 0x25, 0x01, 0xfd, 0xce, 0xcd, 0x70, 0x74, + 0x96, 0x52, 0xf2, 0xc4, 0xf5, 0x54, 0x66, 0x42, 0x4e, 0x5f, 0x4f, 0x65, 0xd2, 0xf2, 0xe4, 0xf5, + 0x54, 0x26, 0x23, 0x67, 0xaf, 0xa7, 0x32, 0x59, 0x19, 0x94, 0xf7, 0x67, 0x21, 0x1f, 0x8e, 0x0c, + 0x48, 0xa0, 0x65, 0x50, 0xdb, 0x28, 0x51, 0xed, 0x79, 0xe6, 0xc0, 0x38, 0x62, 0x71, 0x89, 0x18, + 0xcd, 0x72, 0x9a, 0xb9, 0xe1, 0x2a, 0xc3, 0x24, 0x0e, 0x0b, 0x11, 0x6b, 0xcc, 0xdc, 0x9e, 0x8c, + 0xca, 0xbf, 0xd0, 0x0a, 0xa4, 0x5f, 0x75, 0x29, 0xed, 0x34, 0xa5, 0xfd, 0xc0, 0xc1, 0xb4, 0xaf, + 0x37, 0x28, 0xf1, 0xec, 0xf5, 0x86, 0xb6, 0xbe, 0xa1, 0xae, 0x55, 0x56, 0x55, 0x8e, 0x8e, 0x4e, + 0x40, 0xaa, 0xad, 0xbf, 0xb6, 0x1f, 0x35, 0xaf, 0xb4, 0x08, 0x2d, 0x42, 0xa9, 0x67, 0xb1, 0xa8, + 0x9b, 0x4c, 0x15, 0x81, 0x2a, 0x85, 0xa1, 0x8a, 0x41, 0xed, 0x2a, 0x81, 0x1f, 0x53, 0x3c, 0x4e, + 0x40, 0xea, 0x36, 0xd6, 0x6f, 0x46, 0x8d, 0x20, 0x2d, 0x42, 0xe7, 0x20, 0xdf, 0xc2, 0xdb, 0xbd, + 0x5d, 0xcd, 0xc1, 0x2d, 0xdd, 0xf0, 0xa2, 0xaa, 0x3f, 0x47, 0xab, 0x54, 0x5a, 0x83, 0x5e, 0x84, + 0x2c, 0x99, 0x23, 0x8b, 0xce, 0xf1, 0x14, 0x65, 0xc1, 0x63, 0x07, 0xb3, 0x80, 0x4f, 0xb1, 0x40, + 0x52, 0x03, 0x7c, 0x74, 0x1d, 0xd2, 0x9e, 0xee, 0xec, 0x62, 0x8f, 0x6a, 0xfe, 0x62, 0x4c, 0xba, + 0x2a, 0x86, 0x52, 0x93, 0x62, 0x10, 0xb6, 0x52, 0x19, 0xe5, 0x14, 0xd0, 0x35, 0x98, 0x64, 0x7f, + 0xb9, 0xb3, 0xd3, 0x0b, 0xc9, 0xc3, 0x13, 0x53, 0x05, 0xfa, 0x3b, 0xa8, 0xb3, 0x2e, 0xc0, 0x04, + 0x15, 0x36, 0x04, 0xc0, 0xc5, 0x4d, 0x3e, 0x82, 0x32, 0x90, 0x5a, 0xda, 0x50, 0x89, 0xde, 0x92, + 0x21, 0xcf, 0x4a, 0xb5, 0xcd, 0x7a, 0x6d, 0xa9, 0x26, 0x27, 0x94, 0xcb, 0x90, 0x66, 0x12, 0x44, + 0x74, 0x9a, 0x2f, 0x43, 0xf2, 0x11, 0xfe, 0xc9, 0x69, 0x48, 0xa2, 0x76, 0x6b, 0xad, 0x5a, 0x53, + 0xe5, 0x84, 0xb2, 0x05, 0xa5, 0x3e, 0xae, 0xa3, 0xa3, 0x30, 0xa5, 0xd6, 0x9a, 0xb5, 0x75, 0x12, + 0xb5, 0x69, 0x5b, 0xeb, 0x2f, 0xae, 0x6f, 0xbc, 0x67, 0x5d, 0x3e, 0x12, 0x2d, 0x16, 0x0a, 0x52, + 0x42, 0x33, 0x20, 0x07, 0xc5, 0x8d, 0x8d, 0x2d, 0x95, 0xf6, 0xe6, 0x3b, 0x13, 0x20, 0xf7, 0xb3, + 0x0d, 0x1d, 0x87, 0xe9, 0x66, 0x45, 0x5d, 0xa9, 0x35, 0x35, 0x16, 0x89, 0xfa, 0xa4, 0x67, 0x40, + 0x0e, 0x57, 0x5c, 0xad, 0xd3, 0x40, 0x7b, 0x1e, 0x4e, 0x86, 0x4b, 0x6b, 0x2f, 0x35, 0x6b, 0xeb, + 0x0d, 0xda, 0x78, 0x65, 0x7d, 0x85, 0x68, 0xeb, 0x3e, 0x7a, 0x22, 0xf6, 0x4d, 0x92, 0xae, 0x46, + 0xe9, 0xd5, 0x56, 0x97, 0xe5, 0x54, 0x7f, 0xf1, 0xc6, 0x7a, 0x6d, 0xe3, 0xaa, 0x3c, 0xd1, 0xdf, + 0x3a, 0x8d, 0x87, 0xd3, 0x68, 0x0e, 0x8e, 0xf5, 0x97, 0x6a, 0xb5, 0xf5, 0xa6, 0xfa, 0xb2, 0x3c, + 0xd9, 0xdf, 0x70, 0xa3, 0xa6, 0xde, 0xa8, 0x2f, 0xd5, 0xe4, 0x0c, 0x3a, 0x06, 0x28, 0xda, 0xa3, + 0xe6, 0xb5, 0x8d, 0x65, 0x39, 0x3b, 0xa0, 0x9f, 0x14, 0x17, 0xf2, 0xe1, 0xa0, 0xf4, 0x6b, 0xa2, + 0x1a, 0x95, 0x0f, 0x27, 0x20, 0x17, 0x0a, 0x32, 0x49, 0x74, 0xa0, 0xb7, 0xdb, 0xf6, 0x6d, 0x4d, + 0x6f, 0x9b, 0xba, 0xcb, 0xb5, 0x17, 0xd0, 0xa2, 0x0a, 0x29, 0x19, 0x57, 0x5b, 0x8c, 0x6f, 0x2f, + 0xd2, 0x7f, 0x1d, 0xed, 0xc5, 0x84, 0x9c, 0x56, 0x3e, 0x2e, 0x81, 0xdc, 0x1f, 0x3d, 0xf6, 0x0d, + 0x5f, 0x1a, 0x36, 0xfc, 0xaf, 0xc9, 0xdc, 0x7d, 0x4c, 0x82, 0x62, 0x34, 0x64, 0xec, 0xeb, 0xde, + 0xe9, 0xbf, 0xd2, 0xee, 0xfd, 0x6e, 0x02, 0x0a, 0x91, 0x40, 0x71, 0xdc, 0xde, 0xbd, 0x17, 0xa6, + 0xcc, 0x16, 0xee, 0x74, 0x6d, 0x0f, 0x5b, 0xc6, 0xbe, 0xd6, 0xc6, 0xb7, 0x70, 0x7b, 0x56, 0xa1, + 0x2a, 0xfe, 0xc2, 0xc1, 0xa1, 0xe8, 0x62, 0x3d, 0xc0, 0x5b, 0x25, 0x68, 0xe5, 0xe9, 0xfa, 0x72, + 0x6d, 0x6d, 0x73, 0xa3, 0x59, 0x5b, 0x5f, 0x7a, 0x59, 0x68, 0x17, 0x55, 0x36, 0xfb, 0xc0, 0xde, + 0x41, 0xa5, 0xbd, 0x09, 0x72, 0x7f, 0xa7, 0x88, 0xae, 0x88, 0xe9, 0x96, 0x7c, 0x04, 0x4d, 0x43, + 0x69, 0x7d, 0x43, 0x6b, 0xd4, 0x97, 0x6b, 0x5a, 0xed, 0xea, 0xd5, 0xda, 0x52, 0xb3, 0xc1, 0x92, + 0x8b, 0x3e, 0x74, 0x53, 0x4e, 0x84, 0x59, 0xfc, 0x91, 0x24, 0x4c, 0xc7, 0xf4, 0x04, 0x55, 0x78, + 0x5a, 0x80, 0x65, 0x2a, 0x1e, 0x1b, 0xa7, 0xf7, 0x8b, 0xc4, 0x31, 0xdf, 0xd4, 0x1d, 0x8f, 0x67, + 0x11, 0x1e, 0x06, 0xc2, 0x25, 0xcb, 0x23, 0x7e, 0x82, 0xc3, 0x93, 0xb6, 0x2c, 0x57, 0x50, 0x0a, + 0xca, 0x59, 0xde, 0xf6, 0x51, 0x40, 0x5d, 0xdb, 0x35, 0x3d, 0xf3, 0x16, 0xd6, 0x4c, 0x4b, 0x64, + 0x78, 0x53, 0x0b, 0xd2, 0xb9, 0x94, 0x2a, 0x8b, 0x9a, 0xba, 0xe5, 0xf9, 0xd0, 0x16, 0xde, 0xd5, + 0xfb, 0xa0, 0x89, 0x1f, 0x93, 0x54, 0x65, 0x51, 0xe3, 0x43, 0x9f, 0x86, 0x7c, 0xcb, 0xee, 0x91, + 0x80, 0x8a, 0xc1, 0x11, 0x6d, 0x21, 0xa9, 0x39, 0x56, 0xe6, 0x83, 0xf0, 0x50, 0x39, 0x48, 0x2d, + 0xe7, 0xd5, 0x1c, 0x2b, 0x63, 0x20, 0x67, 0xa1, 0xa4, 0xef, 0xee, 0x3a, 0x84, 0xb8, 0x20, 0xc4, + 0x82, 0xff, 0xa2, 0x5f, 0x4c, 0x01, 0xe7, 0xae, 0x43, 0x46, 0xf0, 0x81, 0xf8, 0xc3, 0x84, 0x13, + 0x5a, 0x97, 0x65, 0xb4, 0x12, 0xe7, 0xb2, 0x6a, 0xc6, 0x12, 0x95, 0xa7, 0x21, 0x6f, 0xba, 0x5a, + 0xb0, 0xb7, 0x99, 0x58, 0x48, 0x9c, 0xcb, 0xa8, 0x39, 0xd3, 0xf5, 0xf7, 0x48, 0x94, 0x4f, 0x24, + 0xa0, 0x18, 0xdd, 0xb5, 0x45, 0xcb, 0x90, 0x69, 0xdb, 0x7c, 0x93, 0x85, 0x1d, 0x19, 0x38, 0x37, + 0x62, 0xa3, 0x77, 0x71, 0x95, 0xc3, 0xab, 0x3e, 0xe6, 0xdc, 0xaf, 0x4b, 0x90, 0x11, 0xc5, 0xe8, + 0x18, 0xa4, 0xba, 0xba, 0xb7, 0x47, 0xc9, 0x4d, 0x54, 0x13, 0xb2, 0xa4, 0xd2, 0x6f, 0x52, 0xee, + 0x76, 0x75, 0xb6, 0x4f, 0xc4, 0xcb, 0xc9, 0x37, 0x99, 0xd7, 0x36, 0xd6, 0x5b, 0x34, 0xb3, 0x60, + 0x77, 0x3a, 0xd8, 0xf2, 0x5c, 0x31, 0xaf, 0xbc, 0x7c, 0x89, 0x17, 0xa3, 0x47, 0x60, 0xca, 0x73, + 0x74, 0xb3, 0x1d, 0x81, 0x4d, 0x51, 0x58, 0x59, 0x54, 0xf8, 0xc0, 0x65, 0x38, 0x21, 0xe8, 0xb6, + 0xb0, 0xa7, 0x1b, 0x7b, 0xb8, 0x15, 0x20, 0xa5, 0x69, 0x06, 0xf1, 0x38, 0x07, 0x58, 0xe6, 0xf5, + 0x02, 0x57, 0xf9, 0x5c, 0x02, 0xa6, 0x44, 0x2e, 0xa4, 0xe5, 0x33, 0x6b, 0x0d, 0x40, 0xb7, 0x2c, + 0xdb, 0x0b, 0xb3, 0x6b, 0x50, 0x94, 0x07, 0xf0, 0x16, 0x2b, 0x3e, 0x92, 0x1a, 0x22, 0x30, 0xf7, + 0x25, 0x09, 0x20, 0xa8, 0x1a, 0xca, 0xb7, 0x79, 0xc8, 0xf1, 0x3d, 0x79, 0x7a, 0xb0, 0x83, 0xa5, + 0xcf, 0x80, 0x15, 0x5d, 0x35, 0xdb, 0x34, 0xc9, 0xb9, 0x8d, 0x77, 0x4d, 0x8b, 0xef, 0xce, 0xb0, + 0x0f, 0x91, 0xe4, 0x4c, 0x05, 0xdb, 0x93, 0x2a, 0x64, 0x5c, 0xdc, 0xd1, 0x2d, 0xcf, 0x34, 0xf8, + 0x7e, 0xcb, 0x95, 0x43, 0x75, 0x7e, 0xb1, 0xc1, 0xb1, 0x55, 0x9f, 0x8e, 0x72, 0x0e, 0x32, 0xa2, + 0x94, 0x38, 0x7e, 0xeb, 0x1b, 0xeb, 0x35, 0xf9, 0x08, 0x9a, 0x84, 0x64, 0xa3, 0xd6, 0x94, 0x25, + 0x12, 0xc4, 0x56, 0x56, 0xeb, 0x95, 0x86, 0x9c, 0xa8, 0xfe, 0x5d, 0x98, 0x36, 0xec, 0x4e, 0x7f, + 0x83, 0x55, 0xb9, 0x2f, 0x81, 0xe8, 0x5e, 0x93, 0x5e, 0x79, 0x8c, 0x03, 0xed, 0xda, 0x6d, 0xdd, + 0xda, 0x5d, 0xb4, 0x9d, 0xdd, 0xe0, 0x58, 0x0c, 0x89, 0x35, 0xdc, 0xd0, 0xe1, 0x98, 0xee, 0xf6, + 0x5f, 0x4a, 0xd2, 0x8f, 0x24, 0x92, 0x2b, 0x9b, 0xd5, 0x9f, 0x48, 0xcc, 0xad, 0x30, 0xc4, 0x4d, + 0x31, 0x1c, 0x15, 0xef, 0xb4, 0xb1, 0x41, 0x3a, 0x0f, 0x1f, 0x4d, 0xc1, 0x94, 0xde, 0x31, 0x2d, + 0xfb, 0x02, 0xfd, 0x97, 0x1f, 0xaa, 0x99, 0xa0, 0x1f, 0x73, 0x23, 0x4f, 0xdf, 0x94, 0xaf, 0x30, + 0x05, 0x86, 0x46, 0xed, 0x61, 0xcf, 0xfe, 0xe9, 0x77, 0xfe, 0xf8, 0x44, 0x90, 0xfb, 0x2c, 0xaf, + 0x81, 0x2c, 0xc2, 0x6e, 0x6c, 0x19, 0x36, 0x91, 0xb6, 0xd1, 0x34, 0xfe, 0x4c, 0xd0, 0x28, 0x71, + 0xdc, 0x1a, 0x47, 0x2d, 0xbf, 0x0b, 0x32, 0x3e, 0x99, 0x83, 0xb7, 0x93, 0x66, 0xff, 0xa7, 0x20, + 0xe2, 0x63, 0x94, 0x5f, 0x00, 0x60, 0xce, 0x0e, 0x4b, 0xcb, 0x1e, 0x8c, 0xff, 0x15, 0x81, 0x9f, + 0xa5, 0x38, 0x44, 0x0b, 0x95, 0x57, 0xa0, 0xd8, 0xb2, 0x2d, 0x4f, 0xb3, 0x3b, 0xa6, 0x87, 0x3b, + 0x5d, 0x6f, 0x7f, 0x14, 0x91, 0x3f, 0x67, 0x44, 0x32, 0x6a, 0x81, 0xe0, 0x6d, 0x08, 0x34, 0xd2, + 0x13, 0xb6, 0xb3, 0x36, 0x4e, 0x4f, 0xfe, 0xc2, 0xef, 0x09, 0xc5, 0x21, 0x3d, 0xa9, 0xd6, 0x7e, + 0xe5, 0xf3, 0xa7, 0xa4, 0xcf, 0x7d, 0xfe, 0x94, 0xf4, 0xbb, 0x9f, 0x3f, 0x25, 0x7d, 0xe8, 0x0b, + 0xa7, 0x8e, 0x7c, 0xee, 0x0b, 0xa7, 0x8e, 0xfc, 0xd6, 0x17, 0x4e, 0x1d, 0x79, 0xe5, 0x91, 0x5d, + 0xd3, 0xdb, 0xeb, 0x6d, 0x2f, 0x1a, 0x76, 0xe7, 0x82, 0x61, 0xbb, 0x1d, 0xdb, 0xe5, 0xff, 0x3d, + 0xe6, 0xb6, 0x6e, 0x72, 0xf9, 0xf1, 0xee, 0x30, 0x29, 0xd8, 0x4e, 0xb3, 0x1d, 0x35, 0xf8, 0xa3, + 0x47, 0x60, 0x66, 0xd7, 0xde, 0xb5, 0xe9, 0xe7, 0x05, 0xf2, 0x17, 0x17, 0x90, 0xac, 0x5f, 0x3a, + 0x86, 0x90, 0xac, 0xc3, 0x34, 0x07, 0xd6, 0xe8, 0xe1, 0x0e, 0x96, 0xc8, 0x42, 0x07, 0xee, 0xa2, + 0xcc, 0xfe, 0xec, 0xef, 0x53, 0x9f, 0x55, 0x9d, 0xe2, 0xa8, 0xa4, 0x8e, 0xe5, 0xba, 0xca, 0x2a, + 0x1c, 0x8d, 0xd0, 0x63, 0x16, 0x04, 0x3b, 0x23, 0x28, 0xfe, 0x7b, 0x4e, 0x71, 0x3a, 0x44, 0xb1, + 0xc1, 0x51, 0xcb, 0x4b, 0x50, 0x38, 0x0c, 0xad, 0x5f, 0xe6, 0xb4, 0xf2, 0x38, 0x4c, 0x64, 0x05, + 0x4a, 0x94, 0x88, 0xd1, 0x73, 0x3d, 0xbb, 0x43, 0xe7, 0xf0, 0x60, 0x32, 0xff, 0xe1, 0xf7, 0x99, + 0x4a, 0x2f, 0x12, 0xb4, 0x25, 0x1f, 0xab, 0x5c, 0x06, 0x7a, 0x9e, 0xa5, 0x85, 0x8d, 0xf6, 0x08, + 0x0a, 0xbf, 0xc2, 0x3b, 0xe2, 0xc3, 0x97, 0x6f, 0xc0, 0x0c, 0xf9, 0x9b, 0x5a, 0xcf, 0x70, 0x4f, + 0x46, 0x6f, 0xb9, 0xcc, 0xfe, 0x97, 0x6f, 0x65, 0x56, 0x63, 0xda, 0x27, 0x10, 0xea, 0x53, 0x68, + 0x16, 0x77, 0xb1, 0xe7, 0x61, 0xc7, 0xd5, 0xf4, 0x76, 0x5c, 0xf7, 0x42, 0x39, 0xeb, 0xd9, 0x1f, + 0xfc, 0x72, 0x74, 0x16, 0x57, 0x18, 0x66, 0xa5, 0xdd, 0x2e, 0x6f, 0xc1, 0xf1, 0x18, 0xa9, 0x18, + 0x83, 0xe6, 0x47, 0x38, 0xcd, 0x99, 0x01, 0xc9, 0x20, 0x64, 0x37, 0x41, 0x94, 0xfb, 0x73, 0x39, + 0x06, 0xcd, 0x8f, 0x72, 0x9a, 0x88, 0xe3, 0x8a, 0x29, 0x25, 0x14, 0xaf, 0xc3, 0xd4, 0x2d, 0xec, + 0x6c, 0xdb, 0x2e, 0xdf, 0x27, 0x18, 0x83, 0xdc, 0xc7, 0x38, 0xb9, 0x12, 0x47, 0xa4, 0x1b, 0x07, + 0x84, 0xd6, 0x33, 0x90, 0xd9, 0xd1, 0x0d, 0x3c, 0x06, 0x89, 0xbb, 0x9c, 0xc4, 0x24, 0x81, 0x27, + 0xa8, 0x15, 0xc8, 0xef, 0xda, 0xdc, 0x81, 0x1a, 0x8d, 0xfe, 0x71, 0x8e, 0x9e, 0x13, 0x38, 0x9c, + 0x44, 0xd7, 0xee, 0xf6, 0xda, 0xc4, 0xbb, 0x1a, 0x4d, 0xe2, 0x87, 0x04, 0x09, 0x81, 0xc3, 0x49, + 0x1c, 0x82, 0xad, 0x6f, 0x08, 0x12, 0x6e, 0x88, 0x9f, 0x2f, 0x40, 0xce, 0xb6, 0xda, 0xfb, 0xb6, + 0x35, 0x4e, 0x27, 0x7e, 0x98, 0x53, 0x00, 0x8e, 0x42, 0x08, 0x3c, 0x0b, 0xd9, 0x71, 0x27, 0xe2, + 0xc7, 0xbe, 0x2c, 0x96, 0x87, 0x98, 0x81, 0x15, 0x28, 0x09, 0x05, 0x65, 0xda, 0xd6, 0x18, 0x24, + 0x7e, 0x9c, 0x93, 0x28, 0x86, 0xd0, 0xf8, 0x30, 0x3c, 0xec, 0x7a, 0xbb, 0x78, 0x1c, 0x22, 0x9f, + 0x10, 0xc3, 0xe0, 0x28, 0x9c, 0x95, 0xdb, 0xd8, 0x32, 0xf6, 0xc6, 0xa3, 0xf0, 0x49, 0xc1, 0x4a, + 0x81, 0x43, 0x48, 0x2c, 0x41, 0xa1, 0xa3, 0x3b, 0xee, 0x9e, 0xde, 0x1e, 0x6b, 0x3a, 0x3e, 0xc5, + 0x69, 0xe4, 0x7d, 0x24, 0xce, 0x91, 0x9e, 0x75, 0x18, 0x32, 0x3f, 0x21, 0x38, 0x12, 0x42, 0xe3, + 0x4b, 0xcf, 0xf5, 0xe8, 0xa6, 0xca, 0x61, 0xa8, 0xfd, 0xa4, 0x58, 0x7a, 0x0c, 0x77, 0x2d, 0x4c, + 0xf1, 0x59, 0xc8, 0xba, 0xe6, 0x6b, 0x63, 0x91, 0xf9, 0x27, 0x62, 0xa6, 0x29, 0x02, 0x41, 0x7e, + 0x19, 0x4e, 0xc4, 0x9a, 0x89, 0x31, 0x88, 0xfd, 0x14, 0x27, 0x76, 0x2c, 0xc6, 0x54, 0x70, 0x95, + 0x70, 0x58, 0x92, 0x3f, 0x2d, 0x54, 0x02, 0xee, 0xa3, 0xb5, 0x49, 0x42, 0x5a, 0x57, 0xdf, 0x39, + 0x1c, 0xd7, 0xfe, 0xa9, 0xe0, 0x1a, 0xc3, 0x8d, 0x70, 0xad, 0x09, 0xc7, 0x38, 0xc5, 0xc3, 0xcd, + 0xeb, 0xcf, 0x08, 0xc5, 0xca, 0xb0, 0xb7, 0xa2, 0xb3, 0xfb, 0xf5, 0x30, 0xe7, 0xb3, 0x53, 0xc4, + 0x4e, 0xae, 0xd6, 0xd1, 0xbb, 0x63, 0x50, 0xfe, 0x59, 0x4e, 0x59, 0x68, 0x7c, 0x3f, 0xf8, 0x72, + 0xd7, 0xf4, 0x2e, 0x21, 0xfe, 0x12, 0xcc, 0x0a, 0xe2, 0x3d, 0xcb, 0xc1, 0x86, 0xbd, 0x6b, 0x99, + 0xaf, 0xe1, 0xd6, 0x18, 0xa4, 0xff, 0x59, 0xdf, 0x54, 0x6d, 0x85, 0xd0, 0x09, 0xe5, 0x3a, 0xc8, + 0xbe, 0xaf, 0xa2, 0x99, 0x9d, 0xae, 0xed, 0x78, 0x23, 0x28, 0x7e, 0x5a, 0xcc, 0x94, 0x8f, 0x57, + 0xa7, 0x68, 0xe5, 0x1a, 0xb0, 0x93, 0x46, 0xe3, 0x8a, 0xe4, 0x67, 0x38, 0xa1, 0x42, 0x80, 0xc5, + 0x15, 0x87, 0x61, 0x77, 0xba, 0xba, 0x33, 0x8e, 0xfe, 0xfb, 0x39, 0xa1, 0x38, 0x38, 0x0a, 0x57, + 0x1c, 0xc4, 0x5f, 0x23, 0xd6, 0x7e, 0x0c, 0x0a, 0x3f, 0x2f, 0x14, 0x87, 0xc0, 0xe1, 0x24, 0x84, + 0xc3, 0x30, 0x06, 0x89, 0x7f, 0x2e, 0x48, 0x08, 0x1c, 0x42, 0xe2, 0xdd, 0x81, 0xa1, 0x75, 0xf0, + 0xae, 0xe9, 0x7a, 0xfc, 0xa8, 0xe0, 0xc1, 0xa4, 0x7e, 0xe1, 0xcb, 0x51, 0x27, 0x4c, 0x0d, 0xa1, + 0x12, 0x4d, 0xc4, 0x3d, 0x7b, 0x1a, 0xd0, 0x8f, 0xee, 0xd8, 0x67, 0x85, 0x26, 0x0a, 0xa1, 0x91, + 0xbe, 0x85, 0x3c, 0x44, 0xc2, 0x76, 0x83, 0x84, 0xb1, 0x63, 0x90, 0xfb, 0x17, 0x7d, 0x9d, 0x6b, + 0x08, 0x5c, 0x42, 0x33, 0xe4, 0xff, 0xf4, 0xac, 0x9b, 0x78, 0x7f, 0x2c, 0xe9, 0xfc, 0xc5, 0x3e, + 0xff, 0x67, 0x8b, 0x61, 0x32, 0x1d, 0x52, 0xea, 0xf3, 0xa7, 0x46, 0x47, 0x40, 0xdf, 0xf2, 0x15, + 0x3e, 0xde, 0xa8, 0x3b, 0x55, 0x5e, 0x25, 0x42, 0x1e, 0x75, 0x7a, 0x46, 0x13, 0xfb, 0xd6, 0xaf, + 0xf8, 0x72, 0x1e, 0xf1, 0x79, 0xca, 0x57, 0xa1, 0x10, 0x71, 0x78, 0x46, 0x93, 0xfa, 0x36, 0x4e, + 0x2a, 0x1f, 0xf6, 0x77, 0xca, 0x97, 0x21, 0x45, 0x9c, 0x97, 0xd1, 0xe8, 0xef, 0xe7, 0xe8, 0x14, + 0xbc, 0xfc, 0x1c, 0x64, 0x84, 0xd3, 0x32, 0x1a, 0xf5, 0x03, 0x1c, 0xd5, 0x47, 0x21, 0xe8, 0xc2, + 0x61, 0x19, 0x8d, 0xfe, 0xf7, 0x05, 0xba, 0x40, 0x21, 0xe8, 0xe3, 0xb3, 0xf0, 0xdf, 0x7c, 0x47, + 0x8a, 0x1b, 0x1d, 0xc1, 0xbb, 0x67, 0x61, 0x92, 0x7b, 0x2a, 0xa3, 0xb1, 0xbf, 0x9d, 0x37, 0x2e, + 0x30, 0xca, 0x4f, 0xc1, 0xc4, 0x98, 0x0c, 0xff, 0x2e, 0x8e, 0xca, 0xe0, 0xcb, 0x4b, 0x90, 0x0b, + 0x79, 0x27, 0xa3, 0xd1, 0xbf, 0x9b, 0xa3, 0x87, 0xb1, 0x48, 0xd7, 0xb9, 0x77, 0x32, 0x9a, 0xc0, + 0x3f, 0x10, 0x5d, 0xe7, 0x18, 0x84, 0x6d, 0xc2, 0x31, 0x19, 0x8d, 0xfd, 0x21, 0xc1, 0x75, 0x81, + 0x52, 0x7e, 0x01, 0xb2, 0xbe, 0xb1, 0x19, 0x8d, 0xff, 0x3d, 0x1c, 0x3f, 0xc0, 0x21, 0x1c, 0x08, + 0x19, 0xbb, 0xd1, 0x24, 0xfe, 0xa1, 0xe0, 0x40, 0x08, 0x8b, 0x2c, 0xa3, 0x7e, 0x07, 0x66, 0x34, + 0xa5, 0xef, 0x15, 0xcb, 0xa8, 0xcf, 0x7f, 0x21, 0xb3, 0x49, 0x75, 0xfe, 0x68, 0x12, 0xdf, 0x27, + 0x66, 0x93, 0xc2, 0x93, 0x6e, 0xf4, 0x7b, 0x04, 0xa3, 0x69, 0xfc, 0x80, 0xe8, 0x46, 0x9f, 0x43, + 0x50, 0xde, 0x04, 0x34, 0xe8, 0x0d, 0x8c, 0xa6, 0xf7, 0x61, 0x4e, 0x6f, 0x6a, 0xc0, 0x19, 0x28, + 0xbf, 0x07, 0x8e, 0xc5, 0x7b, 0x02, 0xa3, 0xa9, 0xfe, 0xe0, 0x57, 0xfa, 0x62, 0xb7, 0xb0, 0x23, + 0x50, 0x6e, 0x06, 0x26, 0x25, 0xec, 0x05, 0x8c, 0x26, 0xfb, 0x91, 0xaf, 0x44, 0x15, 0x77, 0xd8, + 0x09, 0x28, 0x57, 0x00, 0x02, 0x03, 0x3c, 0x9a, 0xd6, 0xc7, 0x38, 0xad, 0x10, 0x12, 0x59, 0x1a, + 0xdc, 0xfe, 0x8e, 0xc6, 0xbf, 0x2b, 0x96, 0x06, 0xc7, 0x20, 0x4b, 0x43, 0x98, 0xde, 0xd1, 0xd8, + 0x1f, 0x17, 0x4b, 0x43, 0xa0, 0x10, 0xc9, 0x0e, 0x59, 0xb7, 0xd1, 0x14, 0x7e, 0x58, 0x48, 0x76, + 0x08, 0xab, 0xbc, 0x0e, 0x53, 0x03, 0x06, 0x71, 0x34, 0xa9, 0x1f, 0xe1, 0xa4, 0xe4, 0x7e, 0x7b, + 0x18, 0x36, 0x5e, 0xdc, 0x18, 0x8e, 0xa6, 0xf6, 0xa3, 0x7d, 0xc6, 0x8b, 0xdb, 0xc2, 0xf2, 0xb3, + 0x90, 0xb1, 0x7a, 0xed, 0x36, 0x59, 0x3c, 0xa3, 0x52, 0x5e, 0xff, 0xfd, 0xab, 0x9c, 0x3b, 0x02, + 0xa1, 0x7c, 0x19, 0x26, 0x70, 0x67, 0x1b, 0xb7, 0x46, 0x61, 0xfe, 0xe1, 0x57, 0x85, 0xc2, 0x24, + 0xd0, 0xe5, 0x17, 0x00, 0x58, 0x6a, 0x84, 0x1e, 0xd2, 0x18, 0x81, 0xfb, 0xa5, 0xaf, 0xf2, 0xc3, + 0x97, 0x01, 0x4a, 0x40, 0x60, 0x9c, 0x4c, 0xdd, 0x97, 0xa3, 0x04, 0xe8, 0x8c, 0x3c, 0x03, 0x93, + 0xaf, 0xba, 0xb6, 0xe5, 0xe9, 0x23, 0x33, 0x96, 0x7f, 0xc4, 0xb1, 0x05, 0x3c, 0x61, 0x58, 0xc7, + 0x76, 0xb0, 0xa7, 0xef, 0xba, 0xa3, 0x70, 0xff, 0x98, 0xe3, 0xfa, 0x08, 0x04, 0xd9, 0xd0, 0x5d, + 0x6f, 0x9c, 0x71, 0xff, 0x0f, 0x81, 0x2c, 0x10, 0x48, 0xa7, 0xc9, 0xdf, 0x37, 0xf1, 0xc8, 0x0c, + 0xe7, 0x9f, 0x88, 0x4e, 0x73, 0xf8, 0xf2, 0x73, 0x90, 0x25, 0x7f, 0xb2, 0x13, 0xd5, 0x23, 0x90, + 0xff, 0x94, 0x23, 0x07, 0x18, 0xa4, 0x65, 0xd7, 0x6b, 0x79, 0xe6, 0x68, 0x66, 0xff, 0x19, 0x9f, + 0x69, 0x01, 0x5f, 0xae, 0x40, 0xce, 0xf5, 0x5a, 0xad, 0x1e, 0xf7, 0x4f, 0x47, 0xe5, 0x87, 0xbf, + 0xea, 0xa7, 0x2c, 0x7c, 0x1c, 0x32, 0xdb, 0xb7, 0x6f, 0x7a, 0x5d, 0x9b, 0xee, 0xc6, 0x8d, 0xcc, + 0x10, 0x73, 0x0a, 0x21, 0x94, 0xf2, 0x12, 0xe4, 0xc9, 0x58, 0xc4, 0x4d, 0x95, 0x91, 0xf9, 0x61, + 0xce, 0x80, 0x08, 0x52, 0xf5, 0x9b, 0x87, 0x25, 0x77, 0xe3, 0xf7, 0x10, 0x60, 0xc5, 0x5e, 0xb1, + 0xd9, 0xee, 0xc1, 0x2b, 0x0f, 0x0e, 0x66, 0x7f, 0xa3, 0x79, 0x5d, 0xfa, 0x17, 0xfc, 0x2f, 0x09, + 0xee, 0x37, 0xec, 0x0e, 0xf6, 0xb6, 0x77, 0xbc, 0x0b, 0x86, 0xb3, 0xdf, 0xf5, 0xec, 0x0b, 0xb7, + 0x2e, 0x5e, 0xb8, 0x89, 0xf7, 0x5d, 0x9e, 0xf8, 0x45, 0xa2, 0x7a, 0x91, 0x55, 0x2f, 0xde, 0xba, + 0x38, 0x17, 0x9b, 0x22, 0x56, 0x5e, 0x82, 0xec, 0x26, 0xbd, 0xb9, 0xfa, 0x22, 0xde, 0x47, 0x73, + 0x30, 0x89, 0x5b, 0x97, 0x2e, 0x5f, 0xbe, 0xf8, 0x0c, 0xdd, 0x8b, 0xcf, 0x5f, 0x3b, 0xa2, 0x8a, + 0x02, 0x74, 0x0a, 0xb2, 0x2e, 0x36, 0xba, 0x97, 0x2e, 0x5f, 0xb9, 0x79, 0x91, 0xee, 0xe3, 0x90, + 0xda, 0xa0, 0xa8, 0x9c, 0xf9, 0xe2, 0x1b, 0xf3, 0xd2, 0x17, 0x7f, 0x78, 0x5e, 0xaa, 0x4e, 0x40, + 0xd2, 0xed, 0x75, 0xaa, 0x6b, 0x43, 0x93, 0xdc, 0x4f, 0x44, 0x86, 0x29, 0xc6, 0x21, 0xfe, 0xd0, + 0xbb, 0xe6, 0x85, 0xc1, 0xd1, 0xf9, 0xc9, 0xee, 0x4f, 0xa5, 0xe0, 0x54, 0xcc, 0xe0, 0xbb, 0x8e, + 0x6d, 0xef, 0x1c, 0x7a, 0xf4, 0x3b, 0x30, 0xb1, 0x49, 0x10, 0xd1, 0x0c, 0x4c, 0x78, 0xb6, 0xa7, + 0xb7, 0xe9, 0xb8, 0x93, 0x2a, 0xfb, 0x20, 0xa5, 0xec, 0xf2, 0x4c, 0x82, 0x95, 0x9a, 0xe2, 0xde, + 0x4c, 0x1b, 0xeb, 0x3b, 0xec, 0x0c, 0x72, 0x92, 0x6e, 0x8f, 0x66, 0x48, 0x01, 0x3d, 0x6e, 0x3c, + 0x03, 0x13, 0x7a, 0x8f, 0xed, 0xec, 0x25, 0xcf, 0xe5, 0x55, 0xf6, 0xa1, 0xac, 0xc2, 0x24, 0x4f, + 0xe1, 0x22, 0x19, 0x92, 0x37, 0xf1, 0x3e, 0xe3, 0xaf, 0x4a, 0xfe, 0x44, 0x17, 0x60, 0x82, 0xf6, + 0x9e, 0x5f, 0xae, 0x38, 0xb1, 0x38, 0xd8, 0xfd, 0x45, 0xda, 0x4b, 0x95, 0xc1, 0x29, 0xd7, 0x21, + 0xb3, 0x6c, 0x77, 0x4c, 0xcb, 0x8e, 0x92, 0xcb, 0x32, 0x72, 0xb4, 0xd3, 0xdd, 0x9e, 0xc7, 0x37, + 0xdb, 0xd8, 0x07, 0x3a, 0x06, 0x69, 0x76, 0x28, 0x9d, 0x6f, 0x4f, 0xf2, 0x2f, 0x65, 0x09, 0x26, + 0x29, 0xed, 0x8d, 0xae, 0x7f, 0x11, 0x4c, 0x0a, 0x5d, 0x04, 0xe3, 0xe4, 0x13, 0x41, 0x6f, 0x11, + 0xa4, 0x5a, 0xba, 0xa7, 0xf3, 0x81, 0xd3, 0xbf, 0x95, 0x17, 0x20, 0xc3, 0x89, 0xb8, 0xe8, 0x09, + 0x48, 0xda, 0x5d, 0x97, 0x6f, 0x30, 0x9e, 0x1c, 0x3a, 0x96, 0x8d, 0x6e, 0x35, 0xf5, 0x2b, 0x6f, + 0xce, 0x1f, 0x51, 0x09, 0xf4, 0x3b, 0x25, 0x2b, 0xdf, 0x9b, 0x80, 0x53, 0x03, 0xfb, 0x1e, 0x5c, + 0x5b, 0x0c, 0xbb, 0x98, 0x5e, 0x86, 0xcc, 0xb2, 0x50, 0x42, 0xb3, 0x30, 0xe9, 0x62, 0xc3, 0xb6, + 0x5a, 0x2e, 0x97, 0x0b, 0xf1, 0x49, 0x98, 0x6c, 0xe9, 0x96, 0xed, 0xf2, 0x1b, 0x14, 0xec, 0xa3, + 0xfa, 0x51, 0xe9, 0x70, 0x6b, 0xbf, 0x20, 0x5a, 0xa2, 0xeb, 0x7f, 0x53, 0x7a, 0xe5, 0xe2, 0xc8, + 0xcd, 0xc3, 0x9b, 0x96, 0x7d, 0xdb, 0xf2, 0x07, 0x11, 0xd9, 0x40, 0x3c, 0xd5, 0xbf, 0x81, 0xf8, + 0x1e, 0xdc, 0x6e, 0xbf, 0x48, 0xe0, 0x9b, 0x04, 0xd5, 0xe7, 0xca, 0xc7, 0x53, 0x83, 0x5c, 0xb9, + 0xed, 0xe8, 0xdd, 0x2e, 0x76, 0xdc, 0x61, 0x5c, 0x39, 0x03, 0xb9, 0xe5, 0xd0, 0x21, 0x81, 0x19, + 0x71, 0x59, 0x47, 0xa2, 0x07, 0x08, 0xd8, 0x87, 0xa2, 0x00, 0x5c, 0x6d, 0xdb, 0xba, 0x17, 0x03, + 0x93, 0x08, 0xc1, 0xd4, 0x2d, 0xef, 0xca, 0x93, 0x31, 0x30, 0x49, 0x01, 0x73, 0x06, 0x72, 0x5b, + 0xc3, 0x80, 0x52, 0x51, 0x42, 0x4f, 0x5c, 0x8a, 0x81, 0x99, 0xe8, 0x23, 0x14, 0x0b, 0x54, 0x10, + 0x40, 0xa7, 0x21, 0x5b, 0xb5, 0xed, 0x76, 0x0c, 0x48, 0x26, 0x44, 0xa7, 0x11, 0x3a, 0xff, 0x10, + 0x01, 0xca, 0x86, 0x3a, 0x54, 0xdd, 0xf7, 0xb0, 0x1b, 0x03, 0x93, 0xe7, 0x30, 0x87, 0x17, 0x90, + 0xf7, 0xf0, 0x79, 0x39, 0xac, 0x80, 0x88, 0xf9, 0xbc, 0x27, 0x01, 0xf9, 0x81, 0x7c, 0x48, 0xc5, + 0x32, 0xaa, 0x44, 0xc3, 0xea, 0x8e, 0xde, 0x11, 0x02, 0x32, 0xe5, 0xaf, 0x6b, 0x5a, 0x3f, 0x54, + 0xc3, 0xce, 0x8d, 0x58, 0x7f, 0x73, 0x23, 0x24, 0x51, 0xf9, 0x6c, 0x12, 0x4a, 0x4b, 0xb6, 0xe5, + 0x62, 0xcb, 0xed, 0xb9, 0x9b, 0xb4, 0x0b, 0xe8, 0x49, 0x98, 0xd8, 0x6e, 0xdb, 0xc6, 0x4d, 0xca, + 0xdb, 0xdc, 0xa5, 0x53, 0x8b, 0x03, 0x9d, 0x59, 0xac, 0x92, 0x7a, 0x06, 0xae, 0x32, 0x60, 0xf4, + 0x1c, 0x64, 0xf0, 0x2d, 0xb3, 0x85, 0x2d, 0x03, 0x73, 0x4d, 0x7b, 0x3a, 0x06, 0xb1, 0xc6, 0x41, + 0x38, 0xae, 0x8f, 0x82, 0xbe, 0x0e, 0xb2, 0xb7, 0xf4, 0xb6, 0xd9, 0xd2, 0x3d, 0xdb, 0xe1, 0x57, + 0x8e, 0x94, 0x18, 0xfc, 0x1b, 0x02, 0x86, 0x13, 0x08, 0x90, 0x50, 0x19, 0x26, 0x6f, 0x61, 0x87, + 0x9e, 0x6f, 0x61, 0x37, 0x81, 0x16, 0xe2, 0xf0, 0x19, 0x04, 0xc7, 0x16, 0x08, 0xe8, 0x32, 0xa4, + 0xf4, 0x6d, 0xc3, 0xa4, 0x47, 0x1f, 0x72, 0x97, 0xee, 0x8f, 0x41, 0xac, 0x54, 0x97, 0xea, 0x0c, + 0x8b, 0x9e, 0xfe, 0xa3, 0xe0, 0xa4, 0xd3, 0xee, 0xbe, 0x65, 0xec, 0x39, 0xb6, 0xb5, 0x4f, 0x0f, + 0xfb, 0xc4, 0x77, 0xba, 0x21, 0x60, 0x44, 0xa7, 0x7d, 0x24, 0xd2, 0xe9, 0x1d, 0xac, 0x7b, 0x3d, + 0x07, 0xf3, 0x7b, 0xf0, 0x71, 0x9d, 0xbe, 0xca, 0x20, 0x44, 0xa7, 0x39, 0x82, 0x52, 0x87, 0x5c, + 0x68, 0x1e, 0xd8, 0x89, 0xf8, 0x3b, 0xda, 0x36, 0x59, 0x24, 0x7c, 0xc1, 0x67, 0x3a, 0xfa, 0x1d, + 0xba, 0x68, 0xd0, 0x71, 0x98, 0x24, 0x95, 0xbb, 0xfc, 0x94, 0x64, 0x52, 0x4d, 0x77, 0xf4, 0x3b, + 0x2b, 0xba, 0x7b, 0x3d, 0x95, 0x49, 0xca, 0x29, 0xe5, 0x53, 0x12, 0x14, 0xa3, 0x53, 0x83, 0x1e, + 0x01, 0x44, 0x30, 0xf4, 0x5d, 0xac, 0x59, 0xbd, 0x8e, 0x46, 0x27, 0x59, 0xd0, 0x2d, 0x75, 0xf4, + 0x3b, 0x95, 0x5d, 0xbc, 0xde, 0xeb, 0xd0, 0x0e, 0xb8, 0x68, 0x0d, 0x64, 0x01, 0x2c, 0x04, 0xd0, + 0x37, 0xb7, 0x03, 0xb7, 0xf2, 0x39, 0x40, 0x35, 0x43, 0x0c, 0xd4, 0x87, 0xff, 0xdb, 0xbc, 0xa4, + 0x16, 0x19, 0x3d, 0xdf, 0x30, 0x44, 0x86, 0x92, 0x8c, 0x0e, 0x45, 0x79, 0x01, 0x4a, 0x7d, 0x52, + 0x80, 0x14, 0x28, 0x74, 0x7b, 0xdb, 0xda, 0x4d, 0xbc, 0x4f, 0xaf, 0x89, 0x31, 0xf3, 0x98, 0x55, + 0x73, 0xdd, 0xde, 0xf6, 0x8b, 0x78, 0x9f, 0xae, 0xbe, 0x72, 0xe6, 0x17, 0x88, 0x03, 0xf5, 0xc6, + 0xbc, 0xa4, 0x3c, 0x02, 0x85, 0x88, 0x18, 0x10, 0x2b, 0xac, 0x77, 0xbb, 0x5c, 0xff, 0x91, 0x3f, + 0x43, 0xc0, 0xaf, 0x40, 0x9e, 0x38, 0x1e, 0xb8, 0xc5, 0x61, 0x1f, 0x82, 0x12, 0x65, 0x85, 0xd6, + 0xcf, 0xeb, 0x02, 0x2d, 0x5e, 0x13, 0x0c, 0x57, 0xa0, 0x10, 0xc0, 0x05, 0x6c, 0xcf, 0x09, 0xa8, + 0x15, 0xdd, 0x55, 0xbe, 0x5f, 0x82, 0x52, 0x9f, 0x6c, 0xa0, 0xe7, 0x20, 0xdb, 0x75, 0xb0, 0x61, + 0xba, 0xec, 0x18, 0xd1, 0x08, 0x16, 0xa6, 0x28, 0xfb, 0x02, 0x0c, 0xb4, 0x0c, 0x05, 0x71, 0xa4, + 0xa4, 0x85, 0xdb, 0xfa, 0xfe, 0xe8, 0x59, 0x60, 0x24, 0xc4, 0x13, 0x29, 0xcb, 0x04, 0x49, 0xf9, + 0x65, 0x09, 0x0a, 0x11, 0xa1, 0x43, 0x2d, 0xb8, 0xff, 0x96, 0xed, 0xe1, 0x70, 0xaa, 0x83, 0x5f, + 0x1d, 0xda, 0xc3, 0xe6, 0xee, 0x9e, 0xc7, 0xbb, 0x7a, 0x72, 0xa0, 0x9d, 0xc0, 0xd0, 0x50, 0x87, + 0x44, 0x52, 0xe7, 0x08, 0x9d, 0x20, 0xe3, 0xc1, 0xee, 0x18, 0x5d, 0xa3, 0x44, 0xd0, 0x06, 0xa0, + 0xee, 0xb6, 0xd7, 0x4f, 0x3a, 0x31, 0x2e, 0x69, 0x99, 0x20, 0x87, 0x09, 0x2a, 0x0d, 0x80, 0x60, + 0xe1, 0xa2, 0xca, 0x38, 0x83, 0x48, 0x1e, 0xd4, 0xc3, 0x72, 0x62, 0x56, 0xaa, 0x6e, 0x7e, 0xf2, + 0xf3, 0xa7, 0x86, 0x1a, 0x9a, 0x57, 0x2e, 0x8d, 0xef, 0x51, 0x09, 0xdd, 0xef, 0x5b, 0x86, 0xbf, + 0x48, 0xc3, 0xe9, 0x41, 0xcb, 0xe0, 0xab, 0xb8, 0xc3, 0x1a, 0x87, 0x83, 0xa3, 0x18, 0xe5, 0x33, + 0x12, 0xe4, 0xfd, 0x95, 0xd4, 0xc0, 0x1e, 0x7a, 0x17, 0x80, 0xdf, 0x96, 0x70, 0x31, 0xef, 0x3b, + 0x48, 0x09, 0xab, 0x21, 0x78, 0xf4, 0x34, 0x64, 0xba, 0x8e, 0xdd, 0xb5, 0x5d, 0x7e, 0xf1, 0x75, + 0x14, 0xae, 0x0f, 0x8d, 0x1e, 0x05, 0x44, 0x03, 0x02, 0xed, 0x96, 0xed, 0x99, 0xd6, 0xae, 0xd6, + 0xb5, 0x6f, 0xf3, 0xf7, 0x04, 0x92, 0xaa, 0x4c, 0x6b, 0x6e, 0xd0, 0x8a, 0x4d, 0x52, 0xae, 0x7c, + 0x5a, 0x82, 0xac, 0x4f, 0x85, 0xf8, 0x90, 0x7a, 0xab, 0xe5, 0x60, 0xd7, 0xe5, 0xae, 0x80, 0xf8, + 0x44, 0xef, 0x82, 0x49, 0xae, 0x14, 0xfc, 0x6b, 0xd5, 0x71, 0xde, 0xb2, 0x88, 0xce, 0xb8, 0xbf, + 0x9c, 0x66, 0x3a, 0x03, 0x9d, 0x86, 0x7c, 0x4c, 0x6f, 0x72, 0xb7, 0x82, 0x8e, 0xd0, 0xe7, 0x8a, + 0xf8, 0x10, 0xb4, 0xae, 0x63, 0xda, 0x8e, 0xe9, 0xed, 0x53, 0xd3, 0x93, 0x54, 0x65, 0x51, 0xb1, + 0xc9, 0xcb, 0x95, 0x36, 0x94, 0x1a, 0x66, 0xa7, 0x4b, 0x3d, 0x3c, 0xde, 0xf5, 0x2b, 0x41, 0x07, + 0xa5, 0x31, 0x3a, 0x38, 0xb4, 0x6b, 0x89, 0x81, 0xae, 0x9d, 0xff, 0x4d, 0x89, 0xdb, 0x86, 0xfa, + 0xf2, 0xd5, 0xb6, 0xbe, 0x8b, 0x2e, 0xc2, 0xd1, 0xea, 0xea, 0xc6, 0xd2, 0x8b, 0x5a, 0x7d, 0x59, + 0xbb, 0xba, 0x5a, 0x59, 0x09, 0x4e, 0xf1, 0xce, 0x1d, 0x7b, 0xfd, 0xee, 0x02, 0x0a, 0xc1, 0x6e, + 0x59, 0xd4, 0xc5, 0x41, 0x17, 0x60, 0x26, 0x8a, 0x52, 0xa9, 0x36, 0x6a, 0xeb, 0x4d, 0x59, 0x9a, + 0x3b, 0xfa, 0xfa, 0xdd, 0x85, 0xa9, 0x10, 0x46, 0x65, 0xdb, 0xc5, 0x96, 0x37, 0x88, 0xb0, 0xb4, + 0xb1, 0xb6, 0x56, 0x6f, 0xca, 0x89, 0x01, 0x84, 0x25, 0xbb, 0xd3, 0x31, 0x3d, 0xf4, 0x30, 0x4c, + 0x45, 0x11, 0xd6, 0xeb, 0xab, 0x72, 0x72, 0x0e, 0xbd, 0x7e, 0x77, 0xa1, 0x18, 0x82, 0x5e, 0x37, + 0xdb, 0x73, 0x99, 0x0f, 0xfe, 0xe8, 0xa9, 0x23, 0x9f, 0xfc, 0xc7, 0xa7, 0xa4, 0xea, 0xea, 0x3b, + 0xb2, 0xf0, 0x7e, 0x20, 0x01, 0xf3, 0xfd, 0x9e, 0x92, 0x67, 0x76, 0xb0, 0xeb, 0xe9, 0x9d, 0xee, + 0x30, 0xa7, 0xfd, 0x59, 0xc8, 0x36, 0x05, 0xcc, 0xa1, 0x63, 0x99, 0xbb, 0x87, 0x74, 0x55, 0x8b, + 0x7e, 0x53, 0xc2, 0x57, 0xbd, 0x34, 0xa6, 0xaf, 0xea, 0x8f, 0xe3, 0x9e, 0x9c, 0xd5, 0xdf, 0x69, + 0xc0, 0x7d, 0x01, 0x13, 0xb7, 0x0d, 0x93, 0x28, 0x11, 0xb6, 0x9a, 0x19, 0x5b, 0x64, 0x5f, 0x66, + 0x49, 0x2d, 0x51, 0x46, 0x07, 0xab, 0x9d, 0xb9, 0x11, 0xe9, 0x85, 0xb9, 0x11, 0xbe, 0xf1, 0xdc, + 0x68, 0x0d, 0x39, 0x44, 0x1d, 0x8e, 0x9a, 0x61, 0xe5, 0x3f, 0x67, 0x61, 0x52, 0xc5, 0xef, 0xed, + 0x61, 0xd7, 0x43, 0x4f, 0x40, 0x0a, 0x1b, 0x7b, 0xf6, 0xe0, 0xca, 0xe4, 0xa3, 0x5c, 0xac, 0x19, + 0x7b, 0x36, 0x07, 0xbe, 0x76, 0x44, 0xa5, 0xc0, 0xe8, 0x0a, 0x4c, 0xec, 0xb4, 0x7b, 0xee, 0x1e, + 0x57, 0x38, 0xa7, 0x06, 0xb1, 0xae, 0x92, 0xea, 0x00, 0x8d, 0x81, 0x93, 0xc6, 0xe8, 0x73, 0x5a, + 0xc9, 0x61, 0x8d, 0xd1, 0x57, 0xb4, 0x82, 0xc6, 0x08, 0x30, 0x5a, 0x02, 0x30, 0x2d, 0xd3, 0xd3, + 0x8c, 0x3d, 0xdd, 0xb4, 0xb8, 0xe7, 0xaa, 0xc4, 0xa1, 0x9a, 0xde, 0x12, 0x01, 0x09, 0xf0, 0xb3, + 0xa6, 0x28, 0x23, 0x3d, 0x7e, 0x6f, 0x0f, 0x3b, 0xc2, 0x7b, 0x8d, 0xe9, 0xf1, 0xbb, 0x49, 0x75, + 0xa8, 0xc7, 0x14, 0x9c, 0x78, 0xfb, 0xec, 0xaa, 0xb7, 0x77, 0x87, 0x3f, 0x60, 0xb2, 0x30, 0x88, + 0x4a, 0x6f, 0x7a, 0x37, 0xef, 0x04, 0xc8, 0x93, 0x06, 0x2b, 0x41, 0xcf, 0x40, 0xda, 0xa0, 0x4a, + 0x80, 0x5e, 0xc0, 0xcc, 0x5d, 0x9a, 0x8f, 0x41, 0xa6, 0xf5, 0x01, 0x2e, 0x47, 0x40, 0x1b, 0x50, + 0x6c, 0x9b, 0xae, 0xa7, 0xb9, 0x96, 0xde, 0x75, 0xf7, 0x6c, 0xcf, 0xa5, 0x6f, 0x88, 0xe5, 0x2e, + 0x3d, 0x34, 0x48, 0x62, 0xd5, 0x74, 0xbd, 0x86, 0x00, 0x0b, 0x28, 0x15, 0xda, 0xe1, 0x72, 0x42, + 0xd0, 0xde, 0xd9, 0xc1, 0x8e, 0x4f, 0x91, 0xbe, 0x3d, 0x16, 0x4b, 0x70, 0x83, 0xc0, 0x09, 0xcc, + 0x10, 0x41, 0x3b, 0x5c, 0x8e, 0xbe, 0x01, 0xa6, 0xdb, 0xb6, 0xde, 0xf2, 0xe9, 0x69, 0xc6, 0x5e, + 0xcf, 0xba, 0x39, 0x5b, 0xa4, 0x54, 0xcf, 0xc7, 0x74, 0xd3, 0xd6, 0x5b, 0x02, 0x79, 0x89, 0x80, + 0x06, 0x94, 0xa7, 0xda, 0xfd, 0x75, 0x48, 0x83, 0x19, 0xbd, 0xdb, 0x6d, 0xef, 0xf7, 0x93, 0x2f, + 0x51, 0xf2, 0x8f, 0x0c, 0x92, 0xaf, 0x10, 0xe8, 0x21, 0xf4, 0x91, 0x3e, 0x50, 0x89, 0xb6, 0x40, + 0xee, 0x3a, 0x98, 0x9e, 0xcc, 0x60, 0x56, 0x4c, 0x6f, 0xd3, 0x3b, 0x92, 0xb9, 0x4b, 0xe7, 0x06, + 0x89, 0x6f, 0x32, 0xc8, 0x4d, 0x0e, 0x18, 0x50, 0x2e, 0x75, 0xa3, 0x35, 0x8c, 0xac, 0x6d, 0x60, + 0x7a, 0x87, 0x9b, 0x93, 0x9d, 0x1a, 0x4e, 0x96, 0x42, 0xc6, 0x92, 0x8d, 0xd4, 0xa0, 0xab, 0x90, + 0x63, 0xef, 0xf6, 0x10, 0xe7, 0x01, 0xd3, 0xbb, 0x95, 0xb9, 0x4b, 0x67, 0x62, 0x96, 0x2b, 0x05, + 0xba, 0x61, 0x7b, 0x38, 0x20, 0x06, 0xd8, 0x2f, 0x44, 0xdb, 0x70, 0x94, 0xde, 0x33, 0xdd, 0xd7, + 0xa2, 0x2e, 0xe2, 0xec, 0x34, 0xa5, 0xf8, 0xe8, 0x20, 0x45, 0xfa, 0xc8, 0xd2, 0xfe, 0x8d, 0xb0, + 0xaf, 0x18, 0x90, 0x9e, 0xbe, 0x35, 0x58, 0x4b, 0x24, 0x6d, 0xc7, 0xb4, 0xf4, 0xb6, 0xf9, 0x1a, + 0x66, 0xf1, 0x14, 0x7d, 0x62, 0x21, 0x56, 0xd2, 0xae, 0x72, 0x38, 0x6a, 0x07, 0x43, 0x92, 0xb6, + 0x13, 0x2e, 0xaf, 0x4e, 0xf2, 0x2c, 0x88, 0x7f, 0x67, 0x78, 0x52, 0xce, 0xb0, 0x7b, 0xc2, 0xd7, + 0x53, 0x19, 0x90, 0x73, 0xca, 0x59, 0xc8, 0x85, 0xf4, 0x14, 0x31, 0x52, 0xdc, 0xcf, 0xe7, 0xb9, + 0x15, 0xf1, 0xa9, 0x14, 0x21, 0x1f, 0x56, 0x4d, 0xca, 0x87, 0x24, 0xc8, 0x85, 0x94, 0x0e, 0xc1, + 0x14, 0xc1, 0x35, 0xc7, 0x14, 0xa1, 0xf3, 0x19, 0x11, 0xe8, 0x88, 0xfa, 0x04, 0x0d, 0xa3, 0xf2, + 0xb4, 0x90, 0xc7, 0x59, 0x68, 0x1e, 0x72, 0xdd, 0x4b, 0x5d, 0x1f, 0x24, 0x49, 0x41, 0xa0, 0x7b, + 0xa9, 0x2b, 0x00, 0x4e, 0x43, 0x9e, 0x0c, 0x5d, 0x0b, 0x47, 0xf0, 0x59, 0x35, 0x47, 0xca, 0x38, + 0x88, 0xf2, 0xeb, 0x09, 0x90, 0xfb, 0x95, 0x19, 0x7a, 0x1a, 0x52, 0x44, 0x8b, 0x73, 0x35, 0x3d, + 0x37, 0x10, 0x23, 0xf8, 0x56, 0x93, 0x45, 0x9b, 0x1f, 0x22, 0xb1, 0x0e, 0xc5, 0x40, 0x27, 0x88, + 0x06, 0xd3, 0x4d, 0x4b, 0x33, 0x5b, 0xe2, 0x9d, 0x4a, 0xfa, 0x5d, 0x6f, 0x91, 0x68, 0xd6, 0x10, + 0x39, 0x11, 0x8d, 0xd9, 0x9e, 0x03, 0x52, 0x12, 0x7d, 0xe9, 0x13, 0xb5, 0x64, 0xf4, 0xe5, 0x53, + 0x56, 0x22, 0x6e, 0x35, 0x7b, 0xfd, 0xe6, 0x74, 0x8c, 0x3c, 0x09, 0x98, 0xad, 0x6e, 0x4b, 0xf7, + 0x30, 0xf7, 0x47, 0xc3, 0x1e, 0xf6, 0x43, 0x50, 0xd2, 0xbb, 0x5d, 0xcd, 0xf5, 0x74, 0x0f, 0xf3, + 0xd8, 0x73, 0x82, 0xfa, 0xbc, 0x05, 0xbd, 0xdb, 0xa5, 0xef, 0x7c, 0xb1, 0xd8, 0xf3, 0x41, 0x28, + 0x12, 0x0d, 0x6f, 0xea, 0x6d, 0x11, 0xd8, 0xa4, 0x59, 0x88, 0xca, 0x4b, 0x79, 0x70, 0xd4, 0x82, + 0x7c, 0x58, 0xb9, 0xfb, 0xa9, 0x67, 0x29, 0x48, 0x3d, 0x93, 0x32, 0x7a, 0xf1, 0x84, 0x71, 0x48, + 0x5c, 0xd6, 0x49, 0x73, 0xb2, 0xcc, 0x29, 0xe6, 0x5f, 0xc4, 0xd1, 0xe9, 0x3a, 0xf6, 0x2d, 0x76, + 0x99, 0x2a, 0xa3, 0xb2, 0x0f, 0xe5, 0x65, 0x28, 0x46, 0xed, 0x00, 0x2a, 0x42, 0xc2, 0xbb, 0xc3, + 0x5b, 0x49, 0x78, 0x77, 0xd0, 0xc5, 0xd0, 0x0b, 0x69, 0xc5, 0x38, 0xeb, 0xc7, 0xf1, 0x83, 0xa7, + 0xbd, 0xae, 0xa7, 0x32, 0x09, 0x39, 0xa9, 0x94, 0xa0, 0x10, 0xb1, 0x12, 0xca, 0x31, 0x98, 0x89, + 0xd3, 0xf9, 0x8a, 0x09, 0x33, 0x71, 0xaa, 0x1b, 0x5d, 0x81, 0x8c, 0xaf, 0xf4, 0x85, 0x04, 0x0d, + 0xb4, 0xee, 0x23, 0xf9, 0xb0, 0x44, 0x76, 0xc8, 0x44, 0xd0, 0x1d, 0x8a, 0x04, 0x8f, 0x3a, 0xba, + 0xdd, 0x6b, 0xba, 0xbb, 0xa7, 0x7c, 0x33, 0xcc, 0x0e, 0xd3, 0xe7, 0x21, 0xc6, 0xb1, 0x54, 0x83, + 0x60, 0xdc, 0x31, 0x48, 0xf3, 0xd7, 0x16, 0x12, 0x34, 0x73, 0xca, 0xbf, 0x08, 0x43, 0x99, 0x6e, + 0x4f, 0xb2, 0x84, 0x2a, 0xfd, 0x50, 0x34, 0x38, 0x31, 0x54, 0xa5, 0x07, 0x5b, 0x2a, 0x3c, 0x07, + 0xcb, 0xb6, 0x54, 0x7c, 0x42, 0xac, 0xb3, 0xec, 0x83, 0xbe, 0xc2, 0x89, 0xad, 0x16, 0x0f, 0x6e, + 0xb2, 0x2a, 0xff, 0x52, 0x3e, 0x92, 0x84, 0x63, 0xf1, 0x7a, 0x1d, 0x2d, 0x40, 0xbe, 0xa3, 0xdf, + 0xd1, 0xbc, 0x68, 0xea, 0x03, 0x3a, 0xfa, 0x9d, 0x26, 0xcf, 0x7b, 0xc8, 0x90, 0xf4, 0xee, 0xb8, + 0xf4, 0x22, 0x57, 0x5e, 0x25, 0x7f, 0xa2, 0x1b, 0x30, 0xd5, 0xb6, 0x0d, 0xbd, 0xad, 0xb5, 0x75, + 0xd7, 0xd3, 0xb8, 0xd9, 0x67, 0xcb, 0xe9, 0x81, 0x61, 0x7a, 0x9a, 0x5d, 0xb7, 0x32, 0x3d, 0xa2, + 0x82, 0xf8, 0x42, 0x28, 0x51, 0x22, 0xab, 0xba, 0xeb, 0xf1, 0xf0, 0xa1, 0x06, 0xb9, 0x8e, 0xe9, + 0x6e, 0xe3, 0x3d, 0xfd, 0x96, 0x69, 0x3b, 0x7c, 0x5d, 0xc5, 0x48, 0xcf, 0x5a, 0x00, 0xc4, 0x49, + 0x85, 0xf1, 0x42, 0x93, 0x32, 0x11, 0x91, 0x66, 0xa1, 0x59, 0xd2, 0x87, 0xd6, 0x2c, 0x8f, 0xc3, + 0x8c, 0x85, 0xef, 0xd0, 0xbb, 0x82, 0x7c, 0xe5, 0x32, 0x49, 0x61, 0x57, 0xfd, 0x10, 0xa9, 0xf3, + 0xd7, 0xba, 0x4b, 0x77, 0xb5, 0x1e, 0x06, 0x3f, 0x60, 0xd4, 0x44, 0x34, 0x9b, 0xa1, 0xd0, 0x25, + 0x51, 0x5e, 0x61, 0xc5, 0xca, 0xeb, 0x74, 0x72, 0xe2, 0xac, 0xa3, 0x60, 0xbd, 0x14, 0xb0, 0xbe, + 0x09, 0x33, 0x1c, 0xbf, 0x15, 0xe1, 0xfe, 0x40, 0x78, 0x1e, 0x75, 0xba, 0x42, 0x5c, 0x47, 0x02, + 0x7f, 0x38, 0xe3, 0x93, 0xf7, 0xc8, 0x78, 0x04, 0x29, 0xca, 0x96, 0x14, 0x53, 0x37, 0xe4, 0xef, + 0xff, 0xd7, 0x26, 0xe3, 0xfd, 0x49, 0x98, 0x1a, 0x70, 0x2c, 0xfc, 0x81, 0x49, 0xb1, 0x03, 0x4b, + 0xc4, 0x0e, 0x2c, 0x79, 0xe8, 0x81, 0xf1, 0xd9, 0x4e, 0x8d, 0x9e, 0xed, 0x89, 0xb7, 0x73, 0xb6, + 0xd3, 0xf7, 0x38, 0xdb, 0xef, 0xe8, 0x3c, 0x7c, 0x4c, 0x82, 0xb9, 0xe1, 0xee, 0x58, 0xec, 0x84, + 0x3c, 0x02, 0x53, 0x7e, 0x57, 0x7c, 0xf2, 0x4c, 0x3d, 0xca, 0x7e, 0x05, 0xa7, 0x3f, 0xd4, 0xe2, + 0x3d, 0x08, 0xc5, 0x3e, 0x6f, 0x91, 0x09, 0x73, 0x21, 0x92, 0x41, 0x54, 0x3e, 0x90, 0x84, 0x99, + 0x38, 0x87, 0x2e, 0x66, 0xc5, 0xaa, 0x30, 0xdd, 0xc2, 0x86, 0xd9, 0xba, 0xe7, 0x05, 0x3b, 0xc5, + 0xd1, 0xff, 0xff, 0x7a, 0x8d, 0x91, 0x93, 0x1f, 0x03, 0xc8, 0xa8, 0xd8, 0xed, 0x12, 0x07, 0x8d, + 0xbd, 0xf6, 0x6c, 0xe0, 0xae, 0x17, 0x64, 0xda, 0x63, 0xe3, 0x06, 0x0e, 0x22, 0xf0, 0x48, 0xfc, + 0xec, 0xe3, 0xa1, 0x27, 0x79, 0x9a, 0x60, 0x68, 0xc0, 0xcf, 0xdc, 0x6f, 0x1f, 0x95, 0xe5, 0x09, + 0x9e, 0x12, 0x79, 0x82, 0xe4, 0xb0, 0xe8, 0x97, 0x3b, 0xe3, 0x3e, 0x1e, 0x4f, 0x14, 0x3c, 0xc9, + 0x13, 0x05, 0xa9, 0x61, 0xcd, 0x31, 0x9f, 0x3d, 0x68, 0xce, 0x64, 0x17, 0xb9, 0xc3, 0x99, 0x82, + 0xf4, 0xb0, 0xa1, 0x86, 0x9c, 0xeb, 0x60, 0xa8, 0x41, 0xaa, 0xe0, 0x29, 0x91, 0x2a, 0x98, 0x1c, + 0xd6, 0x69, 0xee, 0x4d, 0x06, 0x9d, 0x66, 0xb9, 0x82, 0xe7, 0x43, 0xb9, 0x82, 0x6c, 0xff, 0xce, + 0xe0, 0x40, 0xae, 0xc0, 0xc7, 0xf6, 0x93, 0x05, 0x65, 0x3f, 0x59, 0x90, 0x1f, 0x9a, 0x69, 0xe0, + 0x6e, 0xa0, 0x8f, 0x2c, 0xb2, 0x05, 0x9b, 0x03, 0xd9, 0x02, 0x16, 0xdc, 0x9f, 0x1d, 0x99, 0x2d, + 0xf0, 0x49, 0xf5, 0xa5, 0x0b, 0x36, 0x07, 0xd2, 0x05, 0xc5, 0x61, 0x14, 0xfb, 0x7c, 0xce, 0x80, + 0x62, 0x34, 0x5f, 0xf0, 0x8d, 0xf1, 0xf9, 0x82, 0xa1, 0x01, 0x7d, 0x8c, 0x7f, 0xe9, 0x93, 0x8e, + 0x49, 0x18, 0x7c, 0xf3, 0x90, 0x84, 0x81, 0x3c, 0x2c, 0xb0, 0x8d, 0xf3, 0x2e, 0xfd, 0x06, 0xe2, + 0x32, 0x06, 0x37, 0x62, 0x32, 0x06, 0x2c, 0xb4, 0x7f, 0x78, 0x8c, 0x8c, 0x81, 0x4f, 0x7a, 0x20, + 0x65, 0x70, 0x23, 0x26, 0x65, 0x80, 0x86, 0xd3, 0xed, 0x73, 0x8a, 0xc2, 0x74, 0xa3, 0x39, 0x83, + 0x95, 0x68, 0xce, 0x60, 0xfa, 0x60, 0x5f, 0x94, 0x99, 0x76, 0x9f, 0x5a, 0x38, 0x69, 0x60, 0x0c, + 0x4b, 0x1a, 0xb0, 0xb8, 0xfe, 0xb1, 0x31, 0x93, 0x06, 0x3e, 0xed, 0xd8, 0xac, 0xc1, 0xe6, 0x40, + 0xd6, 0xe0, 0xe8, 0x30, 0x81, 0xeb, 0x33, 0x32, 0x81, 0xc0, 0x0d, 0x4d, 0x1b, 0xb0, 0x47, 0xc6, + 0xd8, 0xf3, 0x62, 0x20, 0xe7, 0xae, 0xa7, 0x32, 0x39, 0x39, 0xaf, 0x3c, 0x4c, 0xdc, 0x9a, 0x3e, + 0xbd, 0x47, 0x82, 0x08, 0xec, 0x38, 0xb6, 0x23, 0x8e, 0x65, 0xd0, 0x0f, 0xe5, 0x1c, 0xe4, 0xc3, + 0x2a, 0xee, 0x80, 0x14, 0x43, 0x09, 0x0a, 0x11, 0xad, 0xa6, 0xfc, 0x82, 0x04, 0xf9, 0xb0, 0xbe, + 0x8a, 0x04, 0xa0, 0x59, 0x1e, 0x80, 0x86, 0x12, 0x0f, 0x89, 0x68, 0xe2, 0x61, 0x1e, 0x72, 0x24, + 0x08, 0xeb, 0xcb, 0x29, 0xe8, 0x5d, 0x3f, 0xa7, 0x70, 0x1e, 0xa6, 0xa8, 0x0d, 0x65, 0xe9, 0x09, + 0x6e, 0xa7, 0xd8, 0xfe, 0x4c, 0x89, 0x54, 0x50, 0x66, 0xf0, 0x9d, 0xc7, 0xc7, 0x60, 0x3a, 0x04, + 0xeb, 0x07, 0x77, 0x2c, 0xbc, 0x96, 0x7d, 0xe8, 0x0a, 0x8f, 0xf2, 0x7e, 0x59, 0x82, 0xa9, 0x01, + 0x75, 0x19, 0x9b, 0x37, 0x90, 0xde, 0xae, 0xbc, 0x41, 0xe2, 0xde, 0xf3, 0x06, 0xe1, 0x70, 0x35, + 0x19, 0x0d, 0x57, 0xff, 0x52, 0x82, 0x42, 0x44, 0x6d, 0x93, 0x49, 0x30, 0xec, 0x96, 0x38, 0xc4, + 0x43, 0xff, 0x26, 0x7e, 0x4a, 0xdb, 0xde, 0xe5, 0x61, 0x22, 0xf9, 0x93, 0x40, 0xf9, 0x86, 0x28, + 0xcb, 0xcd, 0x8c, 0x1f, 0x7b, 0x4e, 0x84, 0x8f, 0xf3, 0xf1, 0x23, 0x6e, 0xe9, 0xe0, 0x88, 0x9b, + 0x7f, 0x76, 0x67, 0x32, 0x74, 0x76, 0x07, 0x3d, 0x03, 0x59, 0xba, 0x0b, 0xa0, 0xd9, 0xdd, 0xe0, + 0x87, 0x29, 0x86, 0x1f, 0x6f, 0x73, 0xe9, 0xfe, 0x21, 0x3b, 0x13, 0x17, 0x78, 0x21, 0xd9, 0x88, + 0x17, 0x72, 0x1f, 0x64, 0x49, 0xf7, 0xd9, 0xe3, 0x8e, 0xc0, 0x0f, 0xd3, 0x8a, 0x02, 0xe5, 0x27, + 0x13, 0x50, 0xea, 0xb3, 0x3a, 0xb1, 0x83, 0x17, 0x52, 0x99, 0x08, 0xa5, 0x45, 0xc6, 0x63, 0xc8, + 0x29, 0x80, 0x5d, 0xdd, 0xd5, 0x6e, 0xeb, 0x96, 0xc7, 0xdf, 0x70, 0x4f, 0xaa, 0xa1, 0x12, 0x34, + 0x07, 0x19, 0xf2, 0xd5, 0x73, 0xf9, 0x2b, 0xee, 0x49, 0xd5, 0xff, 0x46, 0x75, 0x48, 0xe3, 0x5b, + 0xf4, 0x39, 0x12, 0xf6, 0xa8, 0xcf, 0xf1, 0x18, 0xf5, 0x44, 0xea, 0xab, 0xb3, 0x64, 0xba, 0xff, + 0xf0, 0xcd, 0x79, 0x99, 0x81, 0x3f, 0xea, 0x3f, 0xbf, 0xa0, 0x72, 0x02, 0x51, 0x36, 0x64, 0xfa, + 0xd8, 0x40, 0xd3, 0x85, 0x79, 0x11, 0xfb, 0x13, 0xa6, 0xb2, 0x0d, 0x4b, 0xb5, 0xd0, 0xc1, 0x9d, + 0xae, 0x6d, 0xb7, 0x35, 0xb6, 0xce, 0x2b, 0x50, 0x8c, 0x1a, 0x59, 0xf6, 0xf2, 0xb2, 0xa7, 0x9b, + 0x96, 0x16, 0xf1, 0x8d, 0xf3, 0xac, 0x90, 0xad, 0xab, 0xeb, 0xa9, 0x8c, 0x24, 0x27, 0x78, 0xba, + 0xe6, 0xdd, 0x70, 0x34, 0xd6, 0xc6, 0xa2, 0xa7, 0x21, 0x1b, 0xd8, 0x67, 0xb6, 0xed, 0x7c, 0x50, + 0x1e, 0x26, 0x00, 0x56, 0x6e, 0xc0, 0xd1, 0x58, 0x23, 0x8b, 0x9e, 0x83, 0xb4, 0x83, 0xdd, 0x5e, + 0xdb, 0xe3, 0xcf, 0x22, 0x3e, 0x38, 0xda, 0x3a, 0xf7, 0xda, 0x9e, 0xca, 0x91, 0x94, 0x8b, 0x70, + 0x62, 0xa8, 0x95, 0x0d, 0xb2, 0x29, 0x52, 0x28, 0x9b, 0xa2, 0xfc, 0xb4, 0x04, 0x73, 0xc3, 0x2d, + 0x27, 0xaa, 0xf6, 0x75, 0xe8, 0xfc, 0x98, 0x76, 0x37, 0xd4, 0x2b, 0x12, 0x6e, 0x38, 0x78, 0x07, + 0x7b, 0xc6, 0x1e, 0x33, 0xe1, 0x4c, 0x29, 0x14, 0xd4, 0x02, 0x2f, 0xa5, 0x38, 0x2e, 0x03, 0x7b, + 0x15, 0x1b, 0x9e, 0xc6, 0x26, 0xd5, 0xe5, 0x3f, 0xb5, 0x53, 0x60, 0xa5, 0x0d, 0x56, 0xa8, 0x3c, + 0x02, 0xc7, 0x87, 0xd8, 0xe2, 0xc1, 0xb8, 0x44, 0x79, 0x85, 0x00, 0xc7, 0x1a, 0x58, 0xf4, 0x02, + 0xa4, 0x5d, 0x4f, 0xf7, 0x7a, 0x2e, 0x1f, 0xd9, 0xd9, 0x91, 0xb6, 0xb9, 0x41, 0xc1, 0x55, 0x8e, + 0xa6, 0x3c, 0x0b, 0x68, 0xd0, 0xd2, 0xc6, 0xc4, 0x56, 0x52, 0x5c, 0x6c, 0xb5, 0x0d, 0x27, 0x0f, + 0xb0, 0xa9, 0x68, 0xa9, 0xaf, 0x73, 0x8f, 0x8c, 0x65, 0x92, 0xfb, 0x3a, 0xf8, 0xc7, 0x09, 0x38, + 0x1a, 0x6b, 0x5a, 0x43, 0xab, 0x54, 0x7a, 0xab, 0xab, 0xf4, 0x39, 0x00, 0xef, 0x8e, 0xc6, 0x66, + 0x5a, 0x68, 0xfb, 0xb8, 0x78, 0xe2, 0x0e, 0x36, 0xa8, 0xc2, 0x22, 0x82, 0x91, 0xf5, 0xf8, 0x5f, + 0x24, 0xf8, 0x0f, 0xc5, 0xb3, 0x3d, 0x6a, 0x09, 0x5c, 0x1e, 0xea, 0x8d, 0x6d, 0x33, 0x82, 0xc0, + 0x97, 0x15, 0xbb, 0xe8, 0x15, 0x38, 0xde, 0x67, 0xd1, 0x7c, 0xda, 0xa9, 0xb1, 0x0d, 0xdb, 0xd1, + 0xa8, 0x61, 0x13, 0xb4, 0xc3, 0x56, 0x69, 0x22, 0x6a, 0x95, 0x5e, 0x01, 0x08, 0x02, 0x5b, 0xb2, + 0xde, 0x1c, 0xbb, 0x67, 0xb5, 0xc4, 0xe1, 0x53, 0xfa, 0x81, 0xae, 0xc0, 0x04, 0x91, 0x04, 0xc1, + 0xaa, 0x18, 0x85, 0x41, 0xa6, 0x34, 0x14, 0x19, 0x33, 0x70, 0xe5, 0x55, 0x21, 0x6d, 0xe1, 0x1c, + 0xe3, 0x90, 0x36, 0x9e, 0x8f, 0xb6, 0xa1, 0x0c, 0x4f, 0x57, 0xc6, 0xb7, 0xf5, 0x77, 0x60, 0x82, + 0x4e, 0x7f, 0xec, 0xd9, 0xef, 0x6f, 0x02, 0xd0, 0x3d, 0xcf, 0x31, 0xb7, 0x7b, 0x41, 0x0b, 0x0b, + 0x43, 0xe4, 0xa7, 0x22, 0x00, 0xab, 0xf7, 0x71, 0x41, 0x9a, 0x09, 0x70, 0x43, 0xc2, 0x14, 0xa2, + 0xa8, 0xac, 0x43, 0x31, 0x8a, 0x1b, 0x7f, 0x98, 0x5d, 0xfc, 0x2a, 0x40, 0x70, 0xd4, 0x36, 0x30, + 0xe4, 0xfc, 0xb6, 0x10, 0xfd, 0x50, 0xbe, 0x25, 0x01, 0xf9, 0xb0, 0xf4, 0xfd, 0x2d, 0x34, 0x96, + 0xca, 0x07, 0x24, 0xc8, 0xf8, 0xe3, 0x8f, 0xa6, 0xf3, 0x23, 0xfb, 0x20, 0xc1, 0xb5, 0x06, 0x3f, + 0x07, 0xcf, 0x76, 0x3d, 0x92, 0xfe, 0xae, 0xc7, 0xbb, 0x7c, 0x83, 0x30, 0x34, 0x98, 0x0f, 0x73, + 0x5b, 0x1c, 0x4f, 0xe2, 0x06, 0xea, 0xd9, 0xf1, 0xce, 0x40, 0xcd, 0xc0, 0x44, 0xf8, 0xf8, 0x12, + 0xfb, 0x50, 0x70, 0xe8, 0x04, 0x25, 0x5b, 0x8d, 0xe1, 0xc3, 0x52, 0xd2, 0xe1, 0x0f, 0x4b, 0xf9, + 0xcd, 0x24, 0xc2, 0xcd, 0xfc, 0x23, 0x09, 0x32, 0x62, 0x5d, 0xa0, 0x17, 0xc2, 0xe7, 0x7b, 0xc5, + 0x61, 0xc1, 0xe1, 0x7a, 0x89, 0x37, 0x10, 0x3a, 0xde, 0x5b, 0x15, 0xfb, 0x8c, 0x66, 0x4b, 0xdb, + 0x69, 0xeb, 0xbb, 0x7c, 0xbb, 0x68, 0xe8, 0xe9, 0x64, 0x76, 0x78, 0x88, 0x1f, 0xb8, 0xac, 0xb7, + 0xc8, 0x07, 0xf7, 0x43, 0xfe, 0x5c, 0x02, 0xb9, 0x7f, 0xdd, 0xbe, 0xf5, 0xfe, 0x0d, 0xda, 0xab, + 0x64, 0x8c, 0xbd, 0x42, 0x17, 0x60, 0x3a, 0xf8, 0x61, 0x2e, 0xd7, 0xdc, 0xb5, 0xd8, 0xe1, 0x5f, + 0x96, 0x54, 0x43, 0x7e, 0x55, 0x43, 0xd4, 0x0c, 0x8e, 0x7b, 0xe2, 0x5e, 0xc7, 0xfd, 0xfe, 0x04, + 0xe4, 0x42, 0x39, 0x3e, 0x74, 0x39, 0xa4, 0x94, 0x8a, 0x71, 0x56, 0x22, 0x04, 0x1c, 0xfa, 0x59, + 0x9d, 0x08, 0xa7, 0x12, 0xf7, 0xc0, 0xa9, 0x61, 0xd9, 0x54, 0x91, 0x34, 0x4c, 0x1d, 0x3a, 0x69, + 0x18, 0x7f, 0x80, 0x70, 0x62, 0xc8, 0x01, 0xc2, 0xbf, 0x27, 0x41, 0xc6, 0x4f, 0xbe, 0x1c, 0x76, + 0x4f, 0xee, 0x18, 0xa4, 0xb9, 0xef, 0xc5, 0x36, 0xe5, 0xf8, 0x57, 0x6c, 0x76, 0x74, 0x0e, 0x32, + 0xe2, 0x95, 0x79, 0x6e, 0xe1, 0xfc, 0xef, 0xf3, 0xdb, 0x90, 0x0b, 0x6d, 0x6b, 0xa2, 0x13, 0x70, + 0x74, 0xe9, 0x5a, 0x6d, 0xe9, 0x45, 0xad, 0xf9, 0x52, 0xff, 0xdb, 0xc2, 0x03, 0x55, 0x6a, 0x8d, + 0x7e, 0xcb, 0x12, 0x3a, 0x0e, 0xd3, 0xd1, 0x2a, 0x56, 0x91, 0x98, 0x4b, 0x7d, 0xf0, 0x47, 0x4f, + 0x1d, 0x39, 0xff, 0xe7, 0x12, 0x4c, 0xc7, 0x78, 0xb9, 0xe8, 0x34, 0xdc, 0xbf, 0x71, 0xf5, 0x6a, + 0x4d, 0xd5, 0x1a, 0xeb, 0x95, 0xcd, 0xc6, 0xb5, 0x8d, 0xa6, 0xa6, 0xd6, 0x1a, 0x5b, 0xab, 0xcd, + 0x50, 0xa3, 0x0b, 0x70, 0x5f, 0x3c, 0x48, 0x65, 0x69, 0xa9, 0xb6, 0xd9, 0x64, 0x8f, 0x1b, 0x0f, + 0x81, 0xa8, 0x6e, 0xa8, 0x4d, 0x39, 0x31, 0x9c, 0x84, 0x5a, 0xbb, 0x5e, 0x5b, 0x6a, 0xca, 0x49, + 0x74, 0x16, 0xce, 0x1c, 0x04, 0xa1, 0x5d, 0xdd, 0x50, 0xd7, 0x2a, 0x4d, 0x39, 0x35, 0x12, 0xb0, + 0x51, 0x5b, 0x5f, 0xae, 0xa9, 0xf2, 0x04, 0x1f, 0xf7, 0x1b, 0x09, 0x98, 0x1d, 0xe6, 0x4c, 0x13, + 0x5a, 0x95, 0xcd, 0xcd, 0xd5, 0x97, 0x03, 0x5a, 0x4b, 0xd7, 0xb6, 0xd6, 0x5f, 0x1c, 0x64, 0xc1, + 0x43, 0xa0, 0x1c, 0x04, 0xe8, 0x33, 0xe2, 0x41, 0x38, 0x7d, 0x20, 0x1c, 0x67, 0xc7, 0x08, 0x30, + 0xb5, 0xd6, 0x54, 0x5f, 0x96, 0x93, 0x68, 0x11, 0xce, 0x8f, 0x04, 0xf3, 0xeb, 0xe4, 0x14, 0xba, + 0x00, 0x8f, 0x1c, 0x0c, 0xcf, 0x18, 0x24, 0x10, 0x04, 0x8b, 0x5e, 0x97, 0xe0, 0x68, 0xac, 0x57, + 0x8e, 0xce, 0xc0, 0xfc, 0xa6, 0xba, 0xb1, 0x54, 0x6b, 0x34, 0xb4, 0x4d, 0x75, 0x63, 0x73, 0xa3, + 0x51, 0x59, 0xd5, 0x1a, 0xcd, 0x4a, 0x73, 0xab, 0x11, 0xe2, 0x8d, 0x02, 0xa7, 0x86, 0x01, 0xf9, + 0x7c, 0x39, 0x00, 0x86, 0x4b, 0x80, 0x90, 0xd3, 0xbb, 0x12, 0x9c, 0x18, 0xea, 0x85, 0xa3, 0x73, + 0xf0, 0x00, 0xfd, 0x9d, 0xb2, 0x97, 0xb5, 0x1b, 0x1b, 0xcd, 0xf0, 0x2b, 0xda, 0x03, 0xbd, 0x3a, + 0x0b, 0x67, 0x0e, 0x84, 0xf4, 0xbb, 0x36, 0x0a, 0xb0, 0xaf, 0x7f, 0xdf, 0x26, 0x41, 0xa9, 0x4f, + 0x17, 0xa2, 0xfb, 0x60, 0x76, 0xad, 0xde, 0xa8, 0xd6, 0xae, 0x55, 0x6e, 0xd4, 0x37, 0xd4, 0xfe, + 0x35, 0x7b, 0x06, 0xe6, 0x07, 0x6a, 0x97, 0xb7, 0x36, 0x57, 0xeb, 0x4b, 0x95, 0x66, 0x8d, 0x36, + 0x2a, 0x4b, 0x64, 0x60, 0x03, 0x40, 0xab, 0xf5, 0x95, 0x6b, 0x4d, 0x6d, 0x69, 0xb5, 0x5e, 0x5b, + 0x6f, 0x6a, 0x95, 0x66, 0xb3, 0x12, 0x2c, 0xe7, 0xea, 0x8b, 0x43, 0x8f, 0xbe, 0x5e, 0x1c, 0xff, + 0xe8, 0x2b, 0x3f, 0xc2, 0x19, 0xdc, 0x56, 0x4b, 0xc0, 0xbc, 0x5f, 0xc9, 0x73, 0x69, 0xfd, 0x47, + 0x3c, 0xa7, 0x7d, 0xed, 0xce, 0x01, 0x86, 0xdf, 0xf8, 0x7c, 0x0e, 0x92, 0x95, 0x6e, 0x97, 0x68, + 0x3e, 0xfa, 0x6d, 0xd8, 0x6d, 0xae, 0x57, 0xfd, 0x6f, 0x52, 0xe7, 0xda, 0x3b, 0xde, 0x6d, 0xdd, + 0xf1, 0x7f, 0x79, 0x4d, 0x7c, 0x2b, 0xcf, 0x40, 0xd6, 0x8f, 0x1e, 0xe8, 0xdb, 0xa5, 0xfe, 0x3d, + 0xa4, 0x94, 0xb8, 0x67, 0xc4, 0x2f, 0x6b, 0x24, 0x82, 0xcb, 0x1a, 0xa9, 0x2f, 0xbe, 0x31, 0x2f, + 0x55, 0xd7, 0x87, 0x72, 0xe7, 0xc9, 0xf1, 0xb9, 0x13, 0x30, 0xc0, 0x67, 0xd0, 0xf7, 0xdd, 0x1f, + 0xba, 0x0d, 0xec, 0x9f, 0x38, 0x0d, 0xb3, 0x27, 0xe6, 0x3c, 0xfe, 0xa8, 0x33, 0xae, 0x63, 0x9c, + 0x61, 0x1d, 0x35, 0x2b, 0xf7, 0x7a, 0xc8, 0xf5, 0x19, 0x28, 0x6c, 0xea, 0x8e, 0xd7, 0xc0, 0xde, + 0x35, 0xac, 0xb7, 0xb0, 0x13, 0xbd, 0x9b, 0x5b, 0x10, 0x77, 0x73, 0x85, 0x3d, 0x4b, 0x04, 0xf6, + 0x4c, 0x31, 0x21, 0x45, 0x9f, 0x13, 0x1e, 0x7a, 0xc8, 0x84, 0x1d, 0x0a, 0xe1, 0x87, 0x4c, 0xe8, + 0x07, 0xba, 0x2c, 0x6e, 0xdf, 0x26, 0x47, 0xdc, 0xbe, 0x15, 0x91, 0x13, 0xbb, 0x83, 0xdb, 0x81, + 0x49, 0xee, 0xcd, 0xc4, 0xee, 0xde, 0xae, 0x43, 0xa9, 0xab, 0x3b, 0x1e, 0xfd, 0xb5, 0x92, 0x3d, + 0x3a, 0x0c, 0xee, 0x89, 0xc4, 0x5d, 0x9f, 0x8a, 0x0c, 0x97, 0x37, 0x53, 0xe8, 0x86, 0x0b, 0x95, + 0x2f, 0xa6, 0x20, 0xcd, 0xd9, 0xf1, 0x7c, 0xf4, 0xa4, 0x5b, 0xc4, 0x31, 0x0f, 0xc4, 0x3f, 0x08, + 0x72, 0x39, 0x41, 0x3f, 0x2d, 0xfd, 0x50, 0xff, 0xb9, 0xb2, 0x6a, 0xee, 0xf3, 0x6f, 0xce, 0x4f, + 0xd2, 0x4c, 0x71, 0x7d, 0x39, 0x38, 0x64, 0xf6, 0xf6, 0x7b, 0x41, 0xcb, 0x50, 0x08, 0xe5, 0xb0, + 0xcd, 0x16, 0xdf, 0xf8, 0x9f, 0x1b, 0xee, 0x29, 0x8a, 0x6d, 0x5e, 0x3f, 0xbf, 0x5d, 0x6f, 0xa1, + 0x73, 0x20, 0x87, 0x76, 0x9e, 0x59, 0x78, 0xce, 0x92, 0xb7, 0xc5, 0xb6, 0xbf, 0xa7, 0x4c, 0x37, + 0x5e, 0x4f, 0x42, 0x96, 0xfe, 0x80, 0x4e, 0x68, 0x7f, 0x36, 0x43, 0x0a, 0x68, 0xe5, 0x59, 0x28, + 0xf5, 0x6f, 0xe1, 0xb2, 0x4d, 0xd9, 0xe2, 0xad, 0xe8, 0xf6, 0xed, 0xb0, 0x0d, 0xdf, 0xec, 0xd0, + 0x0d, 0xdf, 0x07, 0xa1, 0x18, 0x24, 0x25, 0x28, 0x2c, 0x30, 0x4f, 0xdb, 0x2f, 0xa5, 0x60, 0xe1, + 0xfc, 0x42, 0x2e, 0x92, 0x5f, 0xf0, 0x77, 0x06, 0x78, 0xb6, 0x85, 0xc1, 0xe4, 0xd9, 0x9e, 0x31, + 0xa9, 0xe0, 0x49, 0x15, 0x0a, 0x7b, 0x06, 0x0a, 0xe2, 0x92, 0x22, 0x83, 0x2b, 0x50, 0xb8, 0xbc, + 0x28, 0x1c, 0xba, 0x07, 0x5d, 0x8c, 0xdf, 0x83, 0x9e, 0x85, 0xd4, 0x32, 0x8f, 0x8a, 0xfb, 0x72, + 0x6c, 0x9f, 0x4d, 0x42, 0x8a, 0x6e, 0x2b, 0x3d, 0x19, 0x71, 0xcc, 0xe3, 0x44, 0x9a, 0x84, 0x07, + 0xb8, 0xb5, 0xe6, 0xee, 0x86, 0xfc, 0xf2, 0x61, 0x47, 0x4c, 0xfc, 0xd4, 0x46, 0x32, 0x9c, 0xda, + 0xb8, 0x0a, 0x19, 0x5f, 0x4e, 0x52, 0x23, 0xe5, 0xa4, 0x44, 0xe4, 0x84, 0x88, 0x31, 0x2f, 0x50, + 0x27, 0x79, 0x78, 0x81, 0xaa, 0x90, 0xf5, 0x35, 0x8c, 0x2f, 0x70, 0xe3, 0xc8, 0x6c, 0x80, 0x16, + 0x7f, 0x16, 0x23, 0x3d, 0xe4, 0x2c, 0x46, 0x58, 0xb0, 0xf8, 0x6f, 0x6f, 0x4e, 0xd2, 0x81, 0x05, + 0x82, 0xc5, 0x7e, 0x7f, 0xf3, 0x3e, 0xc8, 0x06, 0xf1, 0x15, 0x93, 0xbd, 0xa0, 0x80, 0xd4, 0x06, + 0x91, 0x1a, 0x93, 0xb5, 0xd0, 0x8f, 0x38, 0x0f, 0x89, 0xd2, 0x60, 0x58, 0x94, 0xa6, 0xfc, 0x5b, + 0x09, 0xd2, 0xfc, 0xb8, 0xc5, 0x01, 0x69, 0x01, 0x36, 0x0f, 0x89, 0x61, 0xf3, 0x90, 0x7c, 0x4b, + 0xf3, 0x00, 0x7e, 0x3f, 0xc5, 0x21, 0xd3, 0xfb, 0x62, 0x93, 0x73, 0xa4, 0x93, 0x0d, 0x73, 0x57, + 0xec, 0x13, 0x05, 0x58, 0xca, 0x9b, 0x12, 0x31, 0xbf, 0xbc, 0x7e, 0x30, 0xf0, 0x94, 0x0e, 0x1d, + 0x78, 0x1e, 0xee, 0x94, 0x4d, 0x44, 0x94, 0x92, 0xf7, 0x26, 0x4a, 0x91, 0x49, 0x4f, 0xf5, 0x4d, + 0xba, 0xf2, 0x05, 0x89, 0xff, 0x7e, 0xb3, 0x9f, 0xfc, 0xfb, 0x2b, 0x9a, 0xad, 0xaf, 0xe7, 0xf2, + 0xd5, 0xc2, 0x2d, 0x6d, 0x60, 0xda, 0x1e, 0x88, 0xbb, 0x37, 0x1d, 0xe9, 0x75, 0x30, 0x7d, 0x48, + 0x90, 0x69, 0x04, 0xd3, 0xf8, 0x73, 0x09, 0x71, 0x2a, 0x2d, 0x04, 0xff, 0x37, 0x70, 0x3a, 0xa3, + 0x6b, 0x78, 0x62, 0xcc, 0x35, 0x9c, 0x1e, 0xba, 0x86, 0x7f, 0x2e, 0x41, 0xdf, 0xd9, 0x60, 0x67, + 0x04, 0xbe, 0x16, 0x3a, 0xf8, 0x24, 0x64, 0xbb, 0x76, 0x5b, 0x63, 0x35, 0xec, 0x31, 0xfe, 0x4c, + 0xd7, 0x6e, 0xab, 0x03, 0xa2, 0x36, 0xf1, 0x76, 0x29, 0xe8, 0xf4, 0xdb, 0x30, 0x0d, 0x93, 0xfd, + 0xab, 0xca, 0x83, 0x3c, 0xe3, 0x05, 0xf7, 0xa0, 0x2e, 0x12, 0x26, 0x50, 0x9f, 0x4c, 0xea, 0xf7, + 0xf9, 0xfc, 0x7e, 0x33, 0x50, 0x95, 0x03, 0x12, 0x94, 0xc8, 0x49, 0xb7, 0x13, 0x43, 0x35, 0x97, + 0x38, 0xd9, 0xa3, 0x7c, 0x58, 0x02, 0x58, 0x25, 0xcc, 0xa5, 0x23, 0x26, 0xce, 0x8f, 0x4b, 0x3b, + 0xa1, 0x45, 0xda, 0x9e, 0x1f, 0x3a, 0x71, 0xbc, 0x07, 0x79, 0x37, 0xdc, 0xf5, 0x65, 0x28, 0x04, + 0x02, 0xee, 0x62, 0xd1, 0x9d, 0xf9, 0x83, 0x2e, 0xb2, 0x36, 0xb0, 0xa7, 0xe6, 0x6f, 0x85, 0xbe, + 0x94, 0x7f, 0x27, 0x41, 0x96, 0xf6, 0x6a, 0x0d, 0x7b, 0x7a, 0x64, 0x22, 0xa5, 0xb7, 0x30, 0x91, + 0xf7, 0x03, 0x30, 0x3a, 0xae, 0xf9, 0x1a, 0xe6, 0xf2, 0x95, 0xa5, 0x25, 0x0d, 0xf3, 0x35, 0x8c, + 0x9e, 0xf2, 0xb9, 0x9e, 0x1c, 0xc1, 0x75, 0x91, 0xbc, 0xe5, 0xbc, 0x3f, 0x0e, 0x93, 0x56, 0xaf, + 0xa3, 0xb1, 0xc3, 0xa4, 0x54, 0x68, 0xad, 0x5e, 0xa7, 0x79, 0xc7, 0x55, 0x6e, 0xc2, 0x64, 0xf3, + 0x0e, 0x7b, 0xbf, 0xe7, 0x24, 0x64, 0x1d, 0xdb, 0xe6, 0xde, 0x20, 0x73, 0xc4, 0x33, 0xa4, 0x80, + 0x3a, 0x3f, 0x71, 0x39, 0xff, 0x0b, 0xe3, 0xba, 0xfd, 0xdc, 0xe1, 0x3f, 0xff, 0x9b, 0x12, 0x14, + 0x22, 0x2b, 0x0a, 0x3d, 0x0a, 0xc7, 0x1b, 0xf5, 0x95, 0xf5, 0xda, 0xb2, 0xb6, 0xd6, 0x58, 0xe9, + 0x0b, 0xb0, 0xe7, 0x4a, 0xaf, 0xdf, 0x5d, 0xc8, 0xf1, 0xab, 0xaa, 0xc3, 0xa0, 0x37, 0xd5, 0x1a, + 0x8b, 0xb4, 0x19, 0xf4, 0xa6, 0x83, 0x6f, 0xd9, 0x1e, 0xa6, 0xd0, 0x8f, 0xc3, 0x89, 0x18, 0x68, + 0xff, 0xc2, 0xea, 0xd4, 0xeb, 0x77, 0x17, 0x0a, 0x9b, 0x0e, 0x66, 0xa2, 0x46, 0x31, 0x16, 0x61, + 0x76, 0x10, 0x83, 0x65, 0x35, 0xe4, 0x85, 0x39, 0xf9, 0xf5, 0xbb, 0x0b, 0x79, 0xa1, 0x3b, 0x08, + 0xfc, 0x3b, 0x7e, 0x63, 0xf5, 0xa3, 0x59, 0x38, 0xc1, 0xde, 0xb0, 0xd2, 0x58, 0x0c, 0xc8, 0x3e, + 0x78, 0x48, 0x9a, 0x0f, 0x57, 0x8d, 0xfe, 0x71, 0x02, 0xe5, 0x45, 0x98, 0xae, 0x5b, 0x1e, 0x76, + 0x76, 0xf4, 0xf0, 0xcf, 0x0b, 0xc7, 0xfe, 0x60, 0xef, 0x42, 0xe4, 0x95, 0x4d, 0x1e, 0xc1, 0x87, + 0x8b, 0x94, 0x6f, 0x91, 0x40, 0x6e, 0x18, 0x7a, 0x5b, 0x77, 0xde, 0x2a, 0x29, 0xf4, 0x94, 0xf8, + 0x51, 0x0a, 0x7e, 0x41, 0x24, 0x79, 0xae, 0x78, 0x69, 0x76, 0x31, 0x3c, 0xb8, 0x45, 0xd6, 0x12, + 0xd5, 0xc1, 0xec, 0xc7, 0x28, 0xc8, 0x9f, 0xe7, 0x5f, 0x02, 0x08, 0x2a, 0xd0, 0x49, 0x38, 0xde, + 0x58, 0xaa, 0xac, 0x56, 0xfc, 0x3c, 0x4d, 0x63, 0xb3, 0xb6, 0xc4, 0x7e, 0xf9, 0xfe, 0x08, 0x3a, + 0x06, 0x28, 0x5c, 0xe9, 0xff, 0xce, 0xdc, 0x51, 0x98, 0x0a, 0x97, 0xb3, 0x9f, 0x21, 0x4f, 0x94, + 0xaf, 0x41, 0x89, 0xfd, 0x46, 0x32, 0x31, 0x80, 0xb8, 0xa5, 0x99, 0x16, 0x1a, 0xf1, 0x93, 0xc3, + 0xb3, 0xbf, 0xfa, 0x5f, 0xd9, 0x4f, 0x54, 0x14, 0x18, 0x62, 0x85, 0xe0, 0xd5, 0xad, 0x72, 0x13, + 0x66, 0xe8, 0x8d, 0x70, 0xfa, 0xb3, 0x32, 0x9a, 0x29, 0xf8, 0x3f, 0xfa, 0x0d, 0x41, 0x42, 0x2f, + 0x79, 0x2e, 0xab, 0x4e, 0x07, 0xe8, 0xfe, 0xec, 0x95, 0x5f, 0x0c, 0x7e, 0x54, 0xc4, 0xef, 0xe0, + 0x48, 0x8a, 0xbf, 0xc6, 0x7b, 0x28, 0x9e, 0x10, 0x16, 0x5d, 0x5c, 0x85, 0x29, 0xdd, 0x30, 0x70, + 0x37, 0xd2, 0xbf, 0x11, 0xcf, 0xb6, 0x89, 0xd1, 0xca, 0x1c, 0x33, 0xe8, 0xda, 0x53, 0x90, 0x76, + 0xe9, 0xa4, 0x8c, 0x22, 0x21, 0xba, 0xc3, 0xc1, 0xcb, 0x35, 0x28, 0x32, 0x31, 0xf0, 0x47, 0x34, + 0x82, 0xc0, 0x7f, 0xe4, 0x04, 0xf2, 0x14, 0x4d, 0x8c, 0xc6, 0x82, 0xa9, 0x16, 0x36, 0xda, 0xba, + 0x83, 0x43, 0xa3, 0x39, 0xf8, 0xe9, 0xe2, 0x7f, 0xf9, 0xe9, 0xc7, 0xfd, 0x3d, 0xf4, 0x90, 0xd0, + 0xc5, 0x2c, 0x16, 0x55, 0xe6, 0xb4, 0x83, 0xf1, 0x62, 0x28, 0x8a, 0xf6, 0xf8, 0xb8, 0x0f, 0x6e, + 0xec, 0x5f, 0xf1, 0xc6, 0x4e, 0xc5, 0x49, 0x78, 0xa8, 0xa5, 0x02, 0xa7, 0xca, 0x2a, 0xca, 0x55, + 0x28, 0xec, 0x98, 0xed, 0xd0, 0x74, 0x1f, 0xdc, 0xca, 0xbf, 0xfe, 0xf4, 0xe3, 0x6c, 0xa1, 0x11, + 0x24, 0xce, 0x9a, 0x7b, 0xfa, 0xc9, 0x14, 0x4a, 0xfd, 0xd9, 0x70, 0x57, 0x7d, 0xed, 0xf4, 0x89, + 0x24, 0x9c, 0xe2, 0xc0, 0xdb, 0xba, 0x8b, 0x89, 0xe2, 0xc2, 0x9e, 0x7e, 0xf1, 0x82, 0x61, 0x9b, + 0x56, 0x90, 0x54, 0xa4, 0x0a, 0x8b, 0xd4, 0x2f, 0xf2, 0xfa, 0x21, 0x39, 0xad, 0xe1, 0x8a, 0x6e, + 0x6e, 0xf0, 0x67, 0x7b, 0x94, 0x36, 0xa4, 0x96, 0x6c, 0xd3, 0x22, 0x3e, 0x57, 0x0b, 0x5b, 0x76, + 0x47, 0x9c, 0x57, 0xa4, 0x1f, 0xe8, 0x1a, 0xa4, 0xf5, 0x8e, 0xdd, 0xb3, 0xf8, 0xfb, 0x6d, 0xd5, + 0xc7, 0x89, 0x2d, 0xfc, 0xed, 0x37, 0xe7, 0x8f, 0x32, 0xb2, 0x6e, 0xeb, 0xe6, 0xa2, 0x69, 0x5f, + 0xe8, 0xe8, 0xde, 0x1e, 0x99, 0xe4, 0xdf, 0xf8, 0xcc, 0x63, 0xc0, 0xdb, 0xab, 0x5b, 0xde, 0x27, + 0xff, 0xe0, 0x67, 0xce, 0x4b, 0x2a, 0xc7, 0x67, 0x69, 0x47, 0xa5, 0x0b, 0x93, 0xcb, 0xd8, 0x38, + 0xa0, 0xc1, 0x7a, 0x5f, 0x83, 0x17, 0x79, 0x83, 0x27, 0x07, 0x1b, 0x64, 0xbf, 0x23, 0xb8, 0x8c, + 0x8d, 0x50, 0xb3, 0xcb, 0xd8, 0x88, 0xb6, 0x58, 0x5d, 0xfe, 0xad, 0xdf, 0x3b, 0x75, 0xe4, 0x7d, + 0x9f, 0x3f, 0x75, 0x64, 0xe8, 0x94, 0x29, 0xa3, 0x7f, 0xe5, 0xc6, 0x9f, 0xa9, 0xff, 0x2d, 0xc1, + 0x89, 0x7e, 0xf3, 0xa0, 0x5b, 0xfb, 0xc3, 0xde, 0x3c, 0xb8, 0x02, 0xc9, 0x8a, 0xb5, 0x8f, 0x4e, + 0xb0, 0xd7, 0x5c, 0xb5, 0x9e, 0xd3, 0x16, 0xc7, 0x3c, 0xc9, 0xf7, 0x96, 0xd3, 0x8e, 0x1e, 0x29, + 0xf0, 0x5f, 0xe6, 0xfa, 0xee, 0x43, 0x3e, 0x77, 0x90, 0xa9, 0x58, 0xfb, 0xe2, 0xa1, 0x83, 0x47, + 0xc7, 0x7c, 0xe8, 0x40, 0xb7, 0xf6, 0xbb, 0xdb, 0x87, 0x7d, 0xdf, 0xe0, 0x03, 0x97, 0xe1, 0x01, + 0xce, 0x23, 0xd7, 0xd3, 0x6f, 0x9a, 0xd6, 0xae, 0x2f, 0xac, 0xfc, 0x9b, 0xb3, 0xe2, 0x18, 0x9f, + 0x10, 0x51, 0x2a, 0x44, 0x76, 0x50, 0x02, 0xe7, 0x0e, 0x7c, 0x30, 0x61, 0xee, 0xe0, 0x6c, 0xf2, + 0xdc, 0x88, 0x75, 0x73, 0xd0, 0x62, 0x18, 0xb2, 0x7a, 0x86, 0x4e, 0xef, 0xc8, 0xd7, 0xc3, 0x46, + 0x26, 0x93, 0x3f, 0x2c, 0x41, 0xf1, 0x9a, 0xe9, 0x7a, 0xb6, 0x63, 0x1a, 0x7a, 0x9b, 0x6e, 0xa4, + 0xbf, 0x6b, 0x6c, 0xef, 0xbf, 0x9a, 0x25, 0x4b, 0x81, 0x2f, 0xaa, 0x3d, 0xe1, 0x80, 0xa7, 0x6f, + 0xe9, 0x6d, 0xe6, 0x79, 0x87, 0xf5, 0x6e, 0x3f, 0xdb, 0x43, 0xfb, 0xcb, 0x61, 0x2a, 0x0c, 0xb7, + 0x9c, 0x98, 0x95, 0x94, 0xef, 0x4f, 0x40, 0x89, 0x86, 0x0c, 0x2e, 0x3d, 0x10, 0x46, 0x8f, 0x1c, + 0x5d, 0x87, 0x94, 0xa3, 0x7b, 0xdc, 0x09, 0xa9, 0x5e, 0x39, 0xf4, 0x4a, 0x64, 0xad, 0x50, 0x1a, + 0xe8, 0xdd, 0x90, 0xe9, 0xe8, 0x77, 0x34, 0x4a, 0x2f, 0xf1, 0x96, 0xe8, 0x4d, 0x76, 0xf4, 0x3b, + 0xa4, 0x7f, 0xe8, 0x9b, 0xa0, 0x44, 0x48, 0x1a, 0x7b, 0xba, 0xb5, 0x8b, 0x19, 0xe5, 0xe4, 0x5b, + 0xa2, 0x5c, 0xe8, 0xe8, 0x77, 0x96, 0x28, 0x35, 0x42, 0x9f, 0x6b, 0xac, 0x5f, 0x92, 0xf8, 0xe9, + 0x2a, 0xca, 0x18, 0xa4, 0x83, 0x6c, 0xf8, 0x5f, 0xb4, 0x51, 0x71, 0x68, 0xf9, 0xec, 0x30, 0xde, + 0xf7, 0xb1, 0xb5, 0x5a, 0x20, 0xdd, 0xfb, 0xdc, 0x9b, 0xf3, 0x12, 0x6b, 0xb5, 0x64, 0x0c, 0xb0, + 0x3d, 0xc7, 0x4e, 0x8d, 0x69, 0x34, 0xb3, 0x9d, 0x18, 0x19, 0x84, 0x16, 0x44, 0x10, 0xca, 0x08, + 0x02, 0xc3, 0x26, 0xf5, 0x7c, 0x0c, 0x7f, 0x2a, 0x41, 0x6e, 0x39, 0xe4, 0x27, 0xce, 0xc2, 0x64, + 0xc7, 0xb6, 0xcc, 0x9b, 0xd8, 0xf1, 0x4f, 0x9d, 0xb3, 0x4f, 0x34, 0x07, 0x19, 0xf6, 0x0b, 0x90, + 0xde, 0xbe, 0xd8, 0x6d, 0x12, 0xdf, 0x04, 0xeb, 0x36, 0xde, 0x76, 0x4d, 0xc1, 0x67, 0x55, 0x7c, + 0xa2, 0x87, 0x41, 0x76, 0xb1, 0xd1, 0x73, 0x4c, 0x6f, 0x5f, 0x33, 0x6c, 0xcb, 0xd3, 0x0d, 0x8f, + 0x1f, 0x56, 0x2a, 0x89, 0xf2, 0x25, 0x56, 0x4c, 0x88, 0xb4, 0xb0, 0xa7, 0x9b, 0x6d, 0x76, 0x19, + 0x3b, 0xab, 0x8a, 0x4f, 0xb4, 0x12, 0xda, 0xfe, 0x4f, 0xfb, 0xbb, 0x13, 0xb1, 0x1c, 0x15, 0xbf, + 0x37, 0x1f, 0x16, 0x66, 0x1f, 0x99, 0x8f, 0x79, 0x07, 0x32, 0x02, 0x0c, 0x3d, 0x04, 0xa5, 0xae, + 0x63, 0x53, 0xab, 0xdf, 0x35, 0x0d, 0xad, 0xe7, 0x98, 0x7c, 0xdc, 0x05, 0x5e, 0xbc, 0x69, 0x1a, + 0x5b, 0x8e, 0x89, 0x1e, 0x05, 0xe4, 0xda, 0x06, 0xbd, 0x08, 0xae, 0x5b, 0xad, 0x36, 0x51, 0xd8, + 0x26, 0x3b, 0x6b, 0x96, 0x55, 0x65, 0x56, 0x73, 0x8d, 0x56, 0x6c, 0x39, 0xa6, 0xcb, 0xdb, 0xb9, + 0x3b, 0x19, 0x3e, 0x5b, 0xb4, 0x04, 0xb2, 0xdd, 0xc5, 0x4e, 0x24, 0xe3, 0xc3, 0x96, 0xcf, 0xec, + 0x6f, 0x7c, 0xe6, 0xb1, 0x19, 0x3e, 0x1e, 0x9e, 0xf3, 0x61, 0xaf, 0x38, 0xaa, 0x25, 0x81, 0x21, + 0x52, 0x41, 0x2f, 0x47, 0x0e, 0xc6, 0xf7, 0xb6, 0x83, 0x37, 0x99, 0x66, 0x06, 0xa4, 0xa0, 0x62, + 0xed, 0x57, 0x67, 0x7f, 0x2d, 0x20, 0xcd, 0xe3, 0xc5, 0x4d, 0x7a, 0xd2, 0x28, 0x7c, 0x48, 0x9e, + 0x92, 0x41, 0xc7, 0x20, 0xfd, 0xaa, 0x6e, 0xb6, 0xc5, 0xaf, 0xfb, 0xaa, 0xfc, 0x0b, 0x95, 0xfd, + 0x83, 0x9f, 0x29, 0x9a, 0xc1, 0x51, 0x86, 0xb1, 0xbe, 0x6a, 0x5b, 0xad, 0xe8, 0x79, 0x4f, 0xb4, + 0x04, 0x69, 0xcf, 0xbe, 0x89, 0x2d, 0x3e, 0xa3, 0xd5, 0x47, 0x0e, 0xe1, 0x23, 0xa8, 0x1c, 0x15, + 0x7d, 0x03, 0xc8, 0x2d, 0xdc, 0xc6, 0xbb, 0x2c, 0x95, 0xb0, 0xa7, 0x3b, 0x98, 0xe5, 0xb4, 0xef, + 0xc9, 0x03, 0x28, 0xf9, 0xa4, 0x1a, 0x94, 0x12, 0xda, 0x8c, 0x86, 0x4e, 0x93, 0xfe, 0x9d, 0xae, + 0xd8, 0x31, 0x86, 0x96, 0x4a, 0x58, 0xc2, 0x22, 0xa1, 0xd6, 0xc3, 0x20, 0xf7, 0xac, 0x6d, 0xdb, + 0xa2, 0x3f, 0x8a, 0xc9, 0x93, 0x58, 0x19, 0x76, 0x59, 0xc2, 0x2f, 0xe7, 0x97, 0x25, 0x36, 0xa1, + 0x18, 0x80, 0xd2, 0x25, 0x9d, 0x3d, 0xec, 0x92, 0x2e, 0xf8, 0x04, 0x08, 0x08, 0x5a, 0x03, 0x08, + 0x94, 0x06, 0x4d, 0xb3, 0xe7, 0x86, 0xcf, 0x58, 0xa0, 0x7e, 0xc2, 0x83, 0x09, 0x11, 0x40, 0x16, + 0x4c, 0x77, 0x4c, 0x4b, 0x73, 0x71, 0x7b, 0x47, 0xe3, 0x9c, 0x23, 0x74, 0x73, 0x94, 0xfd, 0xcf, + 0x1f, 0x62, 0x36, 0x7f, 0xfb, 0x33, 0x8f, 0x95, 0x02, 0xd7, 0x69, 0xe1, 0xf1, 0xc5, 0x27, 0x9f, + 0x52, 0xa7, 0x3a, 0xa6, 0xd5, 0xc0, 0xed, 0x9d, 0x65, 0x9f, 0x30, 0x7a, 0x17, 0x9c, 0x0c, 0x18, + 0x62, 0x5b, 0xda, 0x9e, 0xdd, 0x6e, 0x69, 0x0e, 0xde, 0xd1, 0x0c, 0xea, 0xf8, 0xe5, 0x29, 0x1b, + 0x8f, 0xfb, 0x20, 0x1b, 0xd6, 0x35, 0xbb, 0xdd, 0x52, 0xf1, 0xce, 0x12, 0xa9, 0x46, 0x67, 0x20, + 0xe0, 0x86, 0x66, 0xb6, 0xdc, 0xd9, 0xc2, 0x42, 0xf2, 0x5c, 0x4a, 0xcd, 0xfb, 0x85, 0xf5, 0x96, + 0x5b, 0xce, 0x7c, 0xf0, 0x8d, 0xf9, 0x23, 0x5f, 0x7c, 0x63, 0xfe, 0x88, 0x72, 0x95, 0xbe, 0xda, + 0xc6, 0x97, 0x16, 0x76, 0xd1, 0x15, 0xc8, 0xea, 0xe2, 0x83, 0x3d, 0x7c, 0x78, 0xc0, 0xd2, 0x0c, + 0x40, 0x95, 0x4f, 0x49, 0x90, 0x5e, 0xbe, 0xb1, 0xa9, 0x9b, 0x0e, 0xaa, 0x91, 0xc0, 0x48, 0xc8, + 0xea, 0xb8, 0xab, 0x3c, 0x10, 0x6f, 0xb1, 0xcc, 0xd7, 0x87, 0xa5, 0x87, 0xb3, 0xd5, 0xd3, 0xbf, + 0xf1, 0x99, 0xc7, 0xee, 0xe7, 0x64, 0x6e, 0xf4, 0x65, 0x8a, 0x05, 0xbd, 0xfe, 0x0c, 0x72, 0x68, + 0xcc, 0xd7, 0x61, 0x92, 0x75, 0xd5, 0x45, 0x2f, 0xc0, 0x44, 0x97, 0xfc, 0xc1, 0x4f, 0x5c, 0x9f, + 0x1a, 0x2a, 0xf3, 0x14, 0x3e, 0x2c, 0x21, 0x0c, 0x4f, 0xf9, 0x8e, 0x04, 0xc0, 0xf2, 0x8d, 0x1b, + 0x4d, 0xc7, 0xec, 0xb6, 0xb1, 0xf7, 0x76, 0x8d, 0x7d, 0x0b, 0x8e, 0x86, 0x32, 0x87, 0x8e, 0x71, + 0xf8, 0xf1, 0x4f, 0x07, 0x39, 0x44, 0xc7, 0x88, 0x25, 0xdb, 0x72, 0x3d, 0x9f, 0x6c, 0xf2, 0xf0, + 0x64, 0x97, 0x5d, 0x6f, 0x90, 0xb3, 0x2f, 0x41, 0x2e, 0x60, 0x86, 0x8b, 0xea, 0x90, 0xf1, 0xf8, + 0xdf, 0x9c, 0xc1, 0xca, 0x70, 0x06, 0x0b, 0xb4, 0x88, 0xd5, 0x12, 0xe8, 0xca, 0x5f, 0x4a, 0x00, + 0xa1, 0x35, 0xf2, 0xd7, 0x53, 0xc6, 0x48, 0x78, 0xc6, 0x95, 0x73, 0xf2, 0x9e, 0xc3, 0x33, 0x46, + 0x20, 0xc4, 0xd4, 0xef, 0x4a, 0xc0, 0xf4, 0x96, 0x58, 0xbd, 0x7f, 0xfd, 0x79, 0xb0, 0x05, 0x93, + 0xd8, 0xf2, 0x1c, 0xd3, 0xbf, 0x31, 0xf0, 0xf8, 0xb0, 0x39, 0x8f, 0x19, 0x54, 0xcd, 0xf2, 0x9c, + 0xfd, 0xb0, 0x04, 0x08, 0x5a, 0x21, 0x7e, 0x7c, 0x34, 0x09, 0xb3, 0xc3, 0x50, 0xd1, 0x59, 0x28, + 0x19, 0x0e, 0xa6, 0x05, 0xd1, 0x77, 0x38, 0x8b, 0xa2, 0x98, 0x9b, 0x1d, 0x15, 0x88, 0x67, 0x49, + 0x84, 0x8b, 0x80, 0xde, 0x9b, 0x2b, 0x59, 0x0c, 0x28, 0x50, 0xc3, 0xd3, 0x84, 0x92, 0x78, 0x2a, + 0x67, 0x5b, 0x6f, 0xeb, 0x96, 0x21, 0x5c, 0xee, 0x43, 0xd9, 0x7c, 0xf1, 0xdc, 0x4e, 0x95, 0x91, + 0x40, 0x35, 0x98, 0x14, 0xd4, 0x52, 0x87, 0xa7, 0x26, 0x70, 0xd1, 0x69, 0xc8, 0x87, 0x0d, 0x03, + 0xf5, 0x46, 0x52, 0x6a, 0x2e, 0x64, 0x17, 0x46, 0x59, 0x9e, 0xf4, 0x81, 0x96, 0x87, 0x3b, 0x7c, + 0x3f, 0x94, 0x84, 0x29, 0x15, 0xb7, 0xfe, 0xe6, 0x4f, 0xcb, 0x26, 0x00, 0x5b, 0xaa, 0x44, 0x93, + 0xf2, 0x99, 0xb9, 0x87, 0xf5, 0x9e, 0x65, 0x44, 0x96, 0x5d, 0xef, 0x6b, 0x35, 0x43, 0xbf, 0x93, + 0x80, 0x7c, 0x78, 0x86, 0xfe, 0x56, 0x1a, 0x2d, 0xb4, 0x1e, 0xa8, 0x29, 0xb6, 0x51, 0xfe, 0xf0, + 0x30, 0x35, 0x35, 0x20, 0xcd, 0x23, 0xf4, 0xd3, 0x97, 0x92, 0x90, 0xe6, 0x97, 0x6e, 0x37, 0x06, + 0x7c, 0xdb, 0x91, 0x8f, 0x30, 0x17, 0xc4, 0x3b, 0xd6, 0xb1, 0xae, 0xed, 0x83, 0x50, 0x24, 0x41, + 0x7d, 0xe4, 0x26, 0xaf, 0x74, 0xae, 0x40, 0x63, 0xf3, 0xe0, 0x60, 0x13, 0x9a, 0x87, 0x1c, 0x01, + 0x0b, 0xf4, 0x30, 0x81, 0x81, 0x8e, 0x7e, 0xa7, 0xc6, 0x4a, 0xd0, 0x45, 0x40, 0x7b, 0x7e, 0xa6, + 0x45, 0x0b, 0x18, 0x21, 0x9d, 0x2b, 0xd0, 0x17, 0xc9, 0xa7, 0x82, 0x5a, 0x81, 0x72, 0x3f, 0x00, + 0xe9, 0x89, 0xc6, 0xb2, 0x92, 0xfc, 0x67, 0xb2, 0x49, 0xc9, 0x32, 0xcd, 0x4c, 0x7e, 0x9b, 0xc4, + 0xdc, 0xe4, 0xbe, 0xf0, 0x9f, 0x47, 0x29, 0xcd, 0x31, 0x16, 0xc6, 0x9f, 0xbd, 0x39, 0x3f, 0xb7, + 0xaf, 0x77, 0xda, 0x65, 0x25, 0x86, 0x8e, 0x12, 0x97, 0x91, 0x20, 0xce, 0x73, 0x34, 0x7d, 0x80, + 0xea, 0x20, 0xdf, 0xc4, 0xfb, 0x9a, 0xc3, 0x7f, 0x49, 0x5e, 0xdb, 0xc1, 0xe2, 0x2d, 0xf4, 0x13, + 0x8b, 0x31, 0x39, 0xe2, 0xc5, 0x25, 0xdb, 0xb4, 0xf8, 0x16, 0x66, 0xf1, 0x26, 0xde, 0x57, 0x39, + 0xde, 0x55, 0x8c, 0xcb, 0x0f, 0x90, 0xd5, 0xf2, 0xfa, 0x1f, 0xfc, 0xcc, 0xf9, 0x93, 0xa1, 0x7c, + 0xe7, 0x1d, 0x3f, 0xb1, 0xc7, 0xa6, 0x98, 0x38, 0xbe, 0x28, 0x30, 0x42, 0xa1, 0xdb, 0xdb, 0x10, + 0x8a, 0x15, 0xa4, 0x83, 0x63, 0x90, 0x00, 0x3f, 0x12, 0x83, 0x84, 0x96, 0xe8, 0xf3, 0x81, 0x0d, + 0x48, 0x8c, 0x1a, 0x4d, 0x58, 0x3a, 0x39, 0x12, 0x5d, 0xf9, 0x47, 0x94, 0xff, 0x24, 0xc1, 0x89, + 0x01, 0x69, 0xf6, 0xbb, 0x6c, 0x00, 0x72, 0x42, 0x95, 0x54, 0x2a, 0xc4, 0x05, 0x9e, 0x7b, 0x5b, + 0x1c, 0x53, 0xce, 0x80, 0x21, 0x78, 0x7b, 0x8c, 0x19, 0xd7, 0x64, 0xbf, 0x2a, 0xc1, 0x4c, 0xb8, + 0x03, 0xfe, 0x50, 0x1a, 0x90, 0x0f, 0x37, 0xcd, 0x07, 0xf1, 0xc0, 0x38, 0x83, 0x08, 0xf7, 0x3f, + 0x42, 0x04, 0xdd, 0x08, 0x34, 0x06, 0x4b, 0x27, 0x5e, 0x1c, 0x9b, 0x29, 0xa2, 0x63, 0xb1, 0x9a, + 0x83, 0xcd, 0xcd, 0x97, 0x24, 0x48, 0x6d, 0xda, 0x76, 0x1b, 0xbd, 0x17, 0xa6, 0x2c, 0xdb, 0xd3, + 0xc8, 0xca, 0xc2, 0x2d, 0x8d, 0xa7, 0x0e, 0x98, 0x36, 0xae, 0x1d, 0xc8, 0xab, 0x3f, 0x7c, 0x73, + 0x7e, 0x10, 0x33, 0x6e, 0xcf, 0xa1, 0x64, 0xd9, 0x5e, 0x95, 0x02, 0x35, 0x59, 0x76, 0x61, 0x07, + 0x0a, 0xd1, 0xe6, 0x98, 0xc6, 0xae, 0x8c, 0x6a, 0xae, 0x30, 0xb2, 0xa9, 0xfc, 0x76, 0xa8, 0x1d, + 0xf6, 0xb3, 0x43, 0x7f, 0x42, 0x66, 0xee, 0x9b, 0x40, 0xbe, 0xd1, 0x7f, 0x3d, 0xf4, 0x2a, 0x4c, + 0x8a, 0xeb, 0xa0, 0xd2, 0xb8, 0x57, 0x4d, 0xc3, 0xfc, 0xe4, 0xc8, 0x34, 0x5f, 0xfb, 0xb9, 0x04, + 0x9c, 0x58, 0xb2, 0x2d, 0x97, 0x27, 0x7a, 0xf8, 0xaa, 0x66, 0xc9, 0xe5, 0x7d, 0xf4, 0xf0, 0x90, + 0x34, 0x54, 0x7e, 0x30, 0xd9, 0x74, 0x03, 0x4a, 0xc4, 0xc4, 0x1a, 0xb6, 0xf5, 0x16, 0x73, 0x4d, + 0x05, 0xbb, 0xdd, 0xe2, 0x3d, 0xba, 0x89, 0xf7, 0x09, 0x5d, 0x0b, 0xdf, 0x8e, 0xd0, 0x4d, 0xde, + 0x1b, 0x5d, 0x0b, 0xdf, 0x0e, 0xd1, 0x0d, 0xce, 0x0c, 0xa5, 0x22, 0x37, 0x90, 0xae, 0x40, 0x92, + 0xa8, 0xc2, 0x89, 0x43, 0x28, 0x0f, 0x82, 0x10, 0x32, 0x6b, 0x0d, 0x38, 0xc1, 0x33, 0x05, 0xee, + 0xc6, 0x0e, 0xe5, 0x28, 0xa6, 0x03, 0x7a, 0x11, 0xef, 0xc7, 0xa4, 0x0d, 0xf2, 0x63, 0xa5, 0x0d, + 0xce, 0xff, 0xbc, 0x04, 0x10, 0xe4, 0xcc, 0xd0, 0xa3, 0x70, 0xbc, 0xba, 0xb1, 0xbe, 0x1c, 0x5c, + 0xc6, 0x08, 0x6d, 0xad, 0x8b, 0x53, 0x1a, 0x6e, 0x17, 0x1b, 0xe6, 0x8e, 0x89, 0x5b, 0xe8, 0x21, + 0x98, 0x89, 0x42, 0x93, 0xaf, 0xda, 0xb2, 0x2c, 0xcd, 0xe5, 0x5f, 0xbf, 0xbb, 0x90, 0x61, 0x31, + 0x02, 0x6e, 0xa1, 0x73, 0x70, 0x74, 0x10, 0xae, 0xbe, 0xbe, 0x22, 0x27, 0xe6, 0x0a, 0xaf, 0xdf, + 0x5d, 0xc8, 0xfa, 0xc1, 0x04, 0x52, 0x00, 0x85, 0x21, 0x39, 0xbd, 0xe4, 0x1c, 0xbc, 0x7e, 0x77, + 0x21, 0xcd, 0x96, 0x0c, 0xbf, 0xc5, 0xf1, 0x8d, 0x00, 0x75, 0x6b, 0xc7, 0xd1, 0x0d, 0xaa, 0x1a, + 0xe6, 0xe0, 0x58, 0x7d, 0xfd, 0xaa, 0x5a, 0x59, 0x6a, 0xd6, 0x37, 0xd6, 0xfb, 0x4e, 0x04, 0x44, + 0xeb, 0x96, 0x37, 0xb6, 0xaa, 0xab, 0x35, 0xad, 0x51, 0x5f, 0x59, 0x67, 0x57, 0xae, 0x22, 0x75, + 0xef, 0x59, 0x6f, 0xd6, 0xd7, 0x6a, 0x72, 0xa2, 0x7a, 0x65, 0xe8, 0x76, 0xdc, 0x7d, 0x91, 0xc5, + 0x18, 0x98, 0xa3, 0xc8, 0x46, 0xdc, 0xff, 0x0d, 0x00, 0x00, 0xff, 0xff, 0xbf, 0x2e, 0x6f, 0x47, + 0xe8, 0xa7, 0x00, 0x00, } r := bytes.NewReader(gzipped) gzipr, err := compress_gzip.NewReader(r) @@ -2366,6 +2443,41 @@ func (this *Description) Equal(that interface{}) bool { if this.Details != that1.Details { return false } + if !this.Metadata.Equal(&that1.Metadata) { + return false + } + return true +} +func (this *Metadata) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*Metadata) + if !ok { + that2, ok := that.(Metadata) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if this.ProfilePicUri != that1.ProfilePicUri { + return false + } + if len(this.SocialHandleUris) != len(that1.SocialHandleUris) { + return false + } + for i := range this.SocialHandleUris { + if this.SocialHandleUris[i] != that1.SocialHandleUris[i] { + return false + } + } return true } func (this *UnbondingDelegationEntry) Equal(that interface{}) bool { @@ -2703,6 +2815,16 @@ func (m *Description) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + { + size, err := m.Metadata.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintStaking(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x32 if len(m.Details) > 0 { i -= len(m.Details) copy(dAtA[i:], m.Details) @@ -2741,6 +2863,45 @@ func (m *Description) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +func (m *Metadata) 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 *Metadata) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Metadata) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.SocialHandleUris) > 0 { + for iNdEx := len(m.SocialHandleUris) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.SocialHandleUris[iNdEx]) + copy(dAtA[i:], m.SocialHandleUris[iNdEx]) + i = encodeVarintStaking(dAtA, i, uint64(len(m.SocialHandleUris[iNdEx]))) + i-- + dAtA[i] = 0x12 + } + } + if len(m.ProfilePicUri) > 0 { + i -= len(m.ProfilePicUri) + copy(dAtA[i:], m.ProfilePicUri) + i = encodeVarintStaking(dAtA, i, uint64(len(m.ProfilePicUri))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + func (m *Validator) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -2762,20 +2923,20 @@ func (m *Validator) MarshalToSizedBuffer(dAtA []byte) (int, error) { var l int _ = l if len(m.UnbondingIds) > 0 { - dAtA5 := make([]byte, len(m.UnbondingIds)*10) - var j4 int + dAtA6 := make([]byte, len(m.UnbondingIds)*10) + var j5 int for _, num := range m.UnbondingIds { for num >= 1<<7 { - dAtA5[j4] = uint8(uint64(num)&0x7f | 0x80) + dAtA6[j5] = uint8(uint64(num)&0x7f | 0x80) num >>= 7 - j4++ + j5++ } - dAtA5[j4] = uint8(num) - j4++ + dAtA6[j5] = uint8(num) + j5++ } - i -= j4 - copy(dAtA[i:], dAtA5[:j4]) - i = encodeVarintStaking(dAtA, i, uint64(j4)) + i -= j5 + copy(dAtA[i:], dAtA6[:j5]) + i = encodeVarintStaking(dAtA, i, uint64(j5)) i-- dAtA[i] = 0x6a } @@ -2804,12 +2965,12 @@ func (m *Validator) MarshalToSizedBuffer(dAtA []byte) (int, error) { } i-- dAtA[i] = 0x52 - n7, err7 := github_com_cosmos_gogoproto_types.StdTimeMarshalTo(m.UnbondingTime, dAtA[i-github_com_cosmos_gogoproto_types.SizeOfStdTime(m.UnbondingTime):]) - if err7 != nil { - return 0, err7 + n8, err8 := github_com_cosmos_gogoproto_types.StdTimeMarshalTo(m.UnbondingTime, dAtA[i-github_com_cosmos_gogoproto_types.SizeOfStdTime(m.UnbondingTime):]) + if err8 != nil { + return 0, err8 } - i -= n7 - i = encodeVarintStaking(dAtA, i, uint64(n7)) + i -= n8 + i = encodeVarintStaking(dAtA, i, uint64(n8)) i-- dAtA[i] = 0x4a if m.UnbondingHeight != 0 { @@ -3219,12 +3380,12 @@ func (m *UnbondingDelegationEntry) MarshalToSizedBuffer(dAtA []byte) (int, error } i-- dAtA[i] = 0x1a - n10, err10 := github_com_cosmos_gogoproto_types.StdTimeMarshalTo(m.CompletionTime, dAtA[i-github_com_cosmos_gogoproto_types.SizeOfStdTime(m.CompletionTime):]) - if err10 != nil { - return 0, err10 + n11, err11 := github_com_cosmos_gogoproto_types.StdTimeMarshalTo(m.CompletionTime, dAtA[i-github_com_cosmos_gogoproto_types.SizeOfStdTime(m.CompletionTime):]) + if err11 != nil { + return 0, err11 } - i -= n10 - i = encodeVarintStaking(dAtA, i, uint64(n10)) + i -= n11 + i = encodeVarintStaking(dAtA, i, uint64(n11)) i-- dAtA[i] = 0x12 if m.CreationHeight != 0 { @@ -3285,12 +3446,12 @@ func (m *RedelegationEntry) MarshalToSizedBuffer(dAtA []byte) (int, error) { } i-- dAtA[i] = 0x1a - n11, err11 := github_com_cosmos_gogoproto_types.StdTimeMarshalTo(m.CompletionTime, dAtA[i-github_com_cosmos_gogoproto_types.SizeOfStdTime(m.CompletionTime):]) - if err11 != nil { - return 0, err11 + n12, err12 := github_com_cosmos_gogoproto_types.StdTimeMarshalTo(m.CompletionTime, dAtA[i-github_com_cosmos_gogoproto_types.SizeOfStdTime(m.CompletionTime):]) + if err12 != nil { + return 0, err12 } - i -= n11 - i = encodeVarintStaking(dAtA, i, uint64(n11)) + i -= n12 + i = encodeVarintStaking(dAtA, i, uint64(n12)) i-- dAtA[i] = 0x12 if m.CreationHeight != 0 { @@ -3421,12 +3582,12 @@ func (m *Params) MarshalToSizedBuffer(dAtA []byte) (int, error) { i-- dAtA[i] = 0x10 } - n13, err13 := github_com_cosmos_gogoproto_types.StdDurationMarshalTo(m.UnbondingTime, dAtA[i-github_com_cosmos_gogoproto_types.SizeOfStdDuration(m.UnbondingTime):]) - if err13 != nil { - return 0, err13 + n14, err14 := github_com_cosmos_gogoproto_types.StdDurationMarshalTo(m.UnbondingTime, dAtA[i-github_com_cosmos_gogoproto_types.SizeOfStdDuration(m.UnbondingTime):]) + if err14 != nil { + return 0, err14 } - i -= n13 - i = encodeVarintStaking(dAtA, i, uint64(n13)) + i -= n14 + i = encodeVarintStaking(dAtA, i, uint64(n14)) i-- dAtA[i] = 0xa return len(dAtA) - i, nil @@ -3828,6 +3989,27 @@ func (m *Description) Size() (n int) { if l > 0 { n += 1 + l + sovStaking(uint64(l)) } + l = m.Metadata.Size() + n += 1 + l + sovStaking(uint64(l)) + return n +} + +func (m *Metadata) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.ProfilePicUri) + if l > 0 { + n += 1 + l + sovStaking(uint64(l)) + } + if len(m.SocialHandleUris) > 0 { + for _, s := range m.SocialHandleUris { + l = len(s) + n += 1 + l + sovStaking(uint64(l)) + } + } return n } @@ -4799,6 +4981,153 @@ func (m *Description) Unmarshal(dAtA []byte) error { } m.Details = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Metadata", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowStaking + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthStaking + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthStaking + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Metadata.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipStaking(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthStaking + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *Metadata) 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 ErrIntOverflowStaking + } + 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: Metadata: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Metadata: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ProfilePicUri", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowStaking + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthStaking + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthStaking + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ProfilePicUri = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SocialHandleUris", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowStaking + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthStaking + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthStaking + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.SocialHandleUris = append(m.SocialHandleUris, string(dAtA[iNdEx:postIndex])) + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipStaking(dAtA[iNdEx:]) diff --git a/x/staking/types/validator.go b/x/staking/types/validator.go index c2e442d4c55a..6665c037b793 100644 --- a/x/staking/types/validator.go +++ b/x/staking/types/validator.go @@ -3,6 +3,7 @@ package types import ( "bytes" "fmt" + "net/url" "sort" "strings" "time" @@ -188,13 +189,14 @@ func (v Validator) IsUnbonding() bool { // constant used in flags to indicate that description field should not be updated const DoNotModifyDesc = "[do-not-modify]" -func NewDescription(moniker, identity, website, securityContact, details string) Description { +func NewDescription(moniker, identity, website, securityContact, details string, metadata Metadata) Description { return Description{ Moniker: moniker, Identity: identity, Website: website, SecurityContact: securityContact, Details: details, + Metadata: metadata, } } @@ -221,13 +223,18 @@ func (d Description) UpdateDescription(d2 Description) (Description, error) { d2.Details = d.Details } + if d2.Metadata.ProfilePicUri == DoNotModifyDesc { + d2.Metadata.ProfilePicUri = d.Metadata.ProfilePicUri + } + return NewDescription( d2.Moniker, d2.Identity, d2.Website, d2.SecurityContact, d2.Details, - ).EnsureLength() + d.Metadata, + ).Validate() } // EnsureLength ensures the length of a validator's description. @@ -255,6 +262,40 @@ func (d Description) EnsureLength() (Description, error) { return d, nil } +func (d Description) IsEmpty() bool { + return d.Moniker == "" && d.Details == "" && d.Identity == "" && d.Website == "" && d.SecurityContact == "" && + d.Metadata.ProfilePicUri == "" && len(d.Metadata.SocialHandleUris) == 0 +} + +// Validate calls metadata.Validate() description.EnsureLength() +func (d Description) Validate() (Description, error) { + if err := d.Metadata.Validate(); err != nil { + return d, err + } + + return d.EnsureLength() +} + +// Validate checks that the metadata fields are valid. For the ProfilePicUri, checks if a valid URI. +func (m Metadata) Validate() error { + if m.ProfilePicUri != "" { + _, err := url.ParseRequestURI(m.ProfilePicUri) + if err != nil { + return errors.Wrapf(sdkerrors.ErrInvalidRequest, "invalid profile_pic_uri format: %s, err: %s", m.ProfilePicUri, err) + } + } + + if m.SocialHandleUris != nil { + for _, socialHandleUri := range m.SocialHandleUris { + _, err := url.ParseRequestURI(socialHandleUri) + if err != nil { + return errors.Wrapf(sdkerrors.ErrInvalidRequest, "invalid social_handle_uri: %s, err: %s", socialHandleUri, err) + } + } + } + return nil +} + // ModuleValidatorUpdate returns a appmodule.ValidatorUpdate from a staking validator type // with the full validator power. // It replaces the previous ABCIValidatorUpdate function. diff --git a/x/tx/CHANGELOG.md b/x/tx/CHANGELOG.md index 7dfbc54a8a73..9fc07fac5acf 100644 --- a/x/tx/CHANGELOG.md +++ b/x/tx/CHANGELOG.md @@ -33,9 +33,20 @@ Since v0.13.0, x/tx follows Cosmos SDK semver: https://github.com/cosmos/cosmos- ## [Unreleased] +* [#21825](https://github.com/cosmos/cosmos-sdk/pull/21825) Fix decimal encoding and field ordering in Amino JSON encoder. +* [#21850](https://github.com/cosmos/cosmos-sdk/pull/21850) Support bytes field as signer. + +## [v0.13.5](https://github.com/cosmos/cosmos-sdk/releases/tag/x/tx/v0.13.5) - 2024-09-18 + +### Improvements + +* [#21712](https://github.com/cosmos/cosmos-sdk/pull/21712) Add `AminoNameAsTypeURL` option to Amino JSON encoder. + +## [v0.13.4](https://github.com/cosmos/cosmos-sdk/releases/tag/x/tx/v0.13.4) - 2024-08-02 + ### Improvements -* [#21073](https://github.com/cosmos/cosmos-sdk/pull/21073) In Context use sync.Map `getSignersFuncs` map from concurrent writes, we also need to call Validate when using the legacy app. +* [#21073](https://github.com/cosmos/cosmos-sdk/pull/21073) In Context use sync.Map `getSignersFuncs` map from concurrent writes, we also call Validate when creating the Context. ## [v0.13.3](https://github.com/cosmos/cosmos-sdk/releases/tag/x/tx/v0.13.3) - 2024-04-22 diff --git a/x/tx/README.md b/x/tx/README.md index 600981407ade..42d0be357c4b 100644 --- a/x/tx/README.md +++ b/x/tx/README.md @@ -19,18 +19,17 @@ custom signer definitions, allowing developers to tailor the signing process to ## Contents -- [x/tx](#xtx) - - [Abstract](#abstract) - - [Contents](#contents) - - [Signing](#signing) - - [Key Features](#key-features) - - [Decode](#decode) - - [Key Features](#key-features-1) - - [DecodedTx](#decodedtx) - - [Class Diagram](#class-diagram) - - [Decode Sequence Diagram](#decode-sequence-diagram) - - [Disambiguation Note](#disambiguation-note) - - [Disclaimer](#disclaimer) +* [x/tx](#xtx) + * [Abstract](#abstract) + * [Contents](#contents) + * [Signing](#signing) + * [Key Features](#key-features) + * [Decode](#decode) + * [Key Features](#key-features-1) + * [DecodedTx](#decodedtx) + * [Class Diagram](#class-diagram) + * [Decode Sequence Diagram](#decode-sequence-diagram) + * [Disclaimer](#disclaimer) ## Signing @@ -42,6 +41,7 @@ In summary, the signing package is responsible for preparing the data to be sign but doesn't handle the actual signing process (i.e., applying a cryptographic signature to these bytes). ### Key Features + 1. SignModeHandler Interface: this is the core interface that defines how different signing modes should be implemented. 2. SignModeHandler Implementations: * [aminojson](https://github.com/cosmos/cosmos-sdk/blob/v0.50.7/docs/architecture/adr-020-protobuf-transaction-encoding.md#sign_mode_legacy_amino) @@ -60,6 +60,7 @@ designed to work with transactions that follow the [ADR-027](https://github.com/ specification for application-defined raw transaction serialization. ### Key Features + 1. Transaction Decoding: Parses raw transaction bytes into a structured `DecodedTx` object. 2. ADR-027 Compatibility: Ensures compatibility with the ADR-027 specification. 3. Unknown Field Handling: Rejects unknown fields in TxRaw and AuthInfo, while allowing non-critical unknown fields in TxBody. @@ -72,6 +73,7 @@ specification for application-defined raw transaction serialization. components of a transaction after it has been parsed from its raw bytes. Here's a breakdown of its structure: The `DecodedTx` struct has the following fields: + 1. DynamicMessages: A slice of proto.Message interfaces, representing the transaction messages in a dynamic format. 2. Messages: A slice of gogoproto.Message interfaces, representing the transaction messages in the gogo protobuf format. 3. Tx: A pointer to a v1beta1.Tx struct, which represents the full transaction in the Cosmos SDK v1beta1 format. @@ -167,5 +169,5 @@ It's important to clarify that `x/tx` is distinct from `x/auth/tx`: * `x/auth/tx`: This is a separate package and is typically used in the context of building a complete tx is that is going to be broadcast in Cosmos SDK applications. When you see a "tx" module referenced in `app_config.go` or similar application configuration files, it refers to -`x/auth/tx`, not `x/tx` (as it's not an Appmodule). This naming similarity can be confusing, so it's crucial to pay -attention to the import paths and context when working with these packages. \ No newline at end of file +`x/auth/tx/config`, not `x/tx` (as it's not an Appmodule). This naming similarity can be confusing, so it's crucial to pay +attention to the import paths and context when working with these packages. diff --git a/x/tx/decode/unknown_test.go b/x/tx/decode/unknown_test.go index dddabbb40267..7d901a5a29e2 100644 --- a/x/tx/decode/unknown_test.go +++ b/x/tx/decode/unknown_test.go @@ -233,7 +233,6 @@ func TestRejectUnknownFieldsRepeated(t *testing.T) { } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { protoBlob, err := proto.Marshal(tt.in) if err != nil { @@ -294,7 +293,6 @@ func TestRejectUnknownFields_allowUnknownNonCriticals(t *testing.T) { } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { blob, err := proto.Marshal(tt.in) if err != nil { @@ -491,7 +489,6 @@ func TestRejectUnknownFieldsNested(t *testing.T) { } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { protoBlob, err := proto.Marshal(tt.in) if err != nil { @@ -627,7 +624,6 @@ func TestRejectUnknownFieldsFlat(t *testing.T) { } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { blob, err := proto.Marshal(tt.in) if err != nil { diff --git a/x/tx/go.mod b/x/tx/go.mod index 6f5155faf4e2..ed82d6892f5a 100644 --- a/x/tx/go.mod +++ b/x/tx/go.mod @@ -3,8 +3,8 @@ module cosmossdk.io/x/tx go 1.23 require ( - cosmossdk.io/api v0.7.5 - cosmossdk.io/core v1.0.0-alpha.2 + cosmossdk.io/api v0.7.6 + cosmossdk.io/core v1.0.0-alpha.4 cosmossdk.io/errors v1.0.1 cosmossdk.io/math v1.3.0 github.com/cosmos/cosmos-proto v1.0.0-beta.5 @@ -28,9 +28,9 @@ require ( golang.org/x/net v0.29.0 // indirect golang.org/x/sys v0.25.0 // indirect golang.org/x/text v0.18.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect - google.golang.org/grpc v1.66.2 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f // indirect + google.golang.org/grpc v1.67.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/x/tx/go.sum b/x/tx/go.sum index 6fe898f71e7c..d92c41b50631 100644 --- a/x/tx/go.sum +++ b/x/tx/go.sum @@ -1,7 +1,7 @@ -cosmossdk.io/api v0.7.5 h1:eMPTReoNmGUm8DeiQL9DyM8sYDjEhWzL1+nLbI9DqtQ= -cosmossdk.io/api v0.7.5/go.mod h1:IcxpYS5fMemZGqyYtErK7OqvdM0C8kdW3dq8Q/XIG38= -cosmossdk.io/core v1.0.0-alpha.2 h1:epU0Xwces4Rgl5bMhHHkXGaGDcyucNGlC/JDH+Suckg= -cosmossdk.io/core v1.0.0-alpha.2/go.mod h1:abgLjeFLhtuKIYZWSPlVUgQBrKObO7ULV35KYfexE90= +cosmossdk.io/api v0.7.6 h1:PC20PcXy1xYKH2KU4RMurVoFjjKkCgYRbVAD4PdqUuY= +cosmossdk.io/api v0.7.6/go.mod h1:IcxpYS5fMemZGqyYtErK7OqvdM0C8kdW3dq8Q/XIG38= +cosmossdk.io/core v1.0.0-alpha.4 h1:9iuroT9ejDYETCsGkzkvs/wAY/5UFl7nCIINFRxyMJY= +cosmossdk.io/core v1.0.0-alpha.4/go.mod h1:3u9cWq1FAVtiiCrDPpo4LhR+9V6k/ycSG4/Y/tREWCY= cosmossdk.io/errors v1.0.1 h1:bzu+Kcr0kS/1DuPBtUFdWjzLqyUuCiyHjyJB6srBV/0= cosmossdk.io/errors v1.0.1/go.mod h1:MeelVSZThMi4bEakzhhhE/CKqVv3nOJDA25bIqRDu/U= cosmossdk.io/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE= @@ -53,12 +53,12 @@ golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 h1:+rdxYoE3E5htTEWIe15GlN6IfvbURM//Jt0mmkmm6ZU= -google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117/go.mod h1:OimBR/bc1wPO9iV4NC2bpyjy3VnAwZh5EBPQdtaE5oo= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:pPJltXNxVzT4pK9yD8vR9X75DaWYYmLGMsEvBfFQZzQ= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= -google.golang.org/grpc v1.66.2 h1:3QdXkuq3Bkh7w+ywLdLvM56cmGvQHUMZpiCzt6Rqaoo= -google.golang.org/grpc v1.66.2/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y= +google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 h1:wKguEg1hsxI2/L3hUYrpo1RVi48K+uTyzKqprwLXsb8= +google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142/go.mod h1:d6be+8HhtEtucleCbxpPW9PA9XwISACu8nvpPqF0BVo= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f h1:cUMEy+8oS78BWIH9OWazBkzbr090Od9tWBNtZHkOhf0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= +google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E= +google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/x/tx/internal/testpb/signers.proto b/x/tx/internal/testpb/signers.proto index 63eb38cba43b..7244a3657400 100644 --- a/x/tx/internal/testpb/signers.proto +++ b/x/tx/internal/testpb/signers.proto @@ -92,7 +92,7 @@ message DeeplyNestedRepeatedSigner { message BadSigner { option (cosmos.msg.v1.signer) = "signer"; - bytes signer = 1; + int32 signer = 1; } message NoSignerOption { @@ -107,4 +107,4 @@ message ValidatorSigner { service TestSimpleSigner { option (cosmos.msg.v1.service) = true; rpc TestSimpleSigner(SimpleSigner) returns (SimpleSigner) {} -} \ No newline at end of file +} diff --git a/x/tx/internal/testpb/signers.pulsar.go b/x/tx/internal/testpb/signers.pulsar.go index f6e3a3d081c1..91de409223b3 100644 --- a/x/tx/internal/testpb/signers.pulsar.go +++ b/x/tx/internal/testpb/signers.pulsar.go @@ -7900,8 +7900,8 @@ func (x *fastReflection_BadSigner) Interface() protoreflect.ProtoMessage { // While iterating, mutating operations may only be performed // on the current field descriptor. func (x *fastReflection_BadSigner) Range(f func(protoreflect.FieldDescriptor, protoreflect.Value) bool) { - if len(x.Signer) != 0 { - value := protoreflect.ValueOfBytes(x.Signer) + if x.Signer != int32(0) { + value := protoreflect.ValueOfInt32(x.Signer) if !f(fd_BadSigner_signer, value) { return } @@ -7922,7 +7922,7 @@ func (x *fastReflection_BadSigner) Range(f func(protoreflect.FieldDescriptor, pr func (x *fastReflection_BadSigner) Has(fd protoreflect.FieldDescriptor) bool { switch fd.FullName() { case "BadSigner.signer": - return len(x.Signer) != 0 + return x.Signer != int32(0) default: if fd.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: BadSigner")) @@ -7940,7 +7940,7 @@ func (x *fastReflection_BadSigner) Has(fd protoreflect.FieldDescriptor) bool { func (x *fastReflection_BadSigner) Clear(fd protoreflect.FieldDescriptor) { switch fd.FullName() { case "BadSigner.signer": - x.Signer = nil + x.Signer = int32(0) default: if fd.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: BadSigner")) @@ -7959,7 +7959,7 @@ func (x *fastReflection_BadSigner) Get(descriptor protoreflect.FieldDescriptor) switch descriptor.FullName() { case "BadSigner.signer": value := x.Signer - return protoreflect.ValueOfBytes(value) + return protoreflect.ValueOfInt32(value) default: if descriptor.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: BadSigner")) @@ -7981,7 +7981,7 @@ func (x *fastReflection_BadSigner) Get(descriptor protoreflect.FieldDescriptor) func (x *fastReflection_BadSigner) Set(fd protoreflect.FieldDescriptor, value protoreflect.Value) { switch fd.FullName() { case "BadSigner.signer": - x.Signer = value.Bytes() + x.Signer = int32(value.Int()) default: if fd.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: BadSigner")) @@ -8018,7 +8018,7 @@ func (x *fastReflection_BadSigner) Mutable(fd protoreflect.FieldDescriptor) prot func (x *fastReflection_BadSigner) NewField(fd protoreflect.FieldDescriptor) protoreflect.Value { switch fd.FullName() { case "BadSigner.signer": - return protoreflect.ValueOfBytes(nil) + return protoreflect.ValueOfInt32(int32(0)) default: if fd.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: BadSigner")) @@ -8088,9 +8088,8 @@ func (x *fastReflection_BadSigner) ProtoMethods() *protoiface.Methods { var n int var l int _ = l - l = len(x.Signer) - if l > 0 { - n += 1 + l + runtime.Sov(uint64(l)) + if x.Signer != 0 { + n += 1 + runtime.Sov(uint64(x.Signer)) } if x.unknownFields != nil { n += len(x.unknownFields) @@ -8121,12 +8120,10 @@ func (x *fastReflection_BadSigner) ProtoMethods() *protoiface.Methods { i -= len(x.unknownFields) copy(dAtA[i:], x.unknownFields) } - if len(x.Signer) > 0 { - i -= len(x.Signer) - copy(dAtA[i:], x.Signer) - i = runtime.EncodeVarint(dAtA, i, uint64(len(x.Signer))) + if x.Signer != 0 { + i = runtime.EncodeVarint(dAtA, i, uint64(x.Signer)) i-- - dAtA[i] = 0xa + dAtA[i] = 0x8 } if input.Buf != nil { input.Buf = append(input.Buf, dAtA...) @@ -8178,10 +8175,10 @@ func (x *fastReflection_BadSigner) ProtoMethods() *protoiface.Methods { } switch fieldNum { case 1: - if wireType != 2 { + if wireType != 0 { return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field Signer", wireType) } - var byteLen int + x.Signer = 0 for shift := uint(0); ; shift += 7 { if shift >= 64 { return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow @@ -8191,26 +8188,11 @@ func (x *fastReflection_BadSigner) ProtoMethods() *protoiface.Methods { } b := dAtA[iNdEx] iNdEx++ - byteLen |= int(b&0x7F) << shift + x.Signer |= int32(b&0x7F) << shift if b < 0x80 { break } } - if byteLen < 0 { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength - } - postIndex := iNdEx + byteLen - if postIndex < 0 { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength - } - if postIndex > l { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF - } - x.Signer = append(x.Signer[:0], dAtA[iNdEx:postIndex]...) - if x.Signer == nil { - x.Signer = []byte{} - } - iNdEx = postIndex default: iNdEx = preIndex skippy, err := runtime.Skip(dAtA[iNdEx:]) @@ -9386,7 +9368,7 @@ type BadSigner struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Signer []byte `protobuf:"bytes,1,opt,name=signer,proto3" json:"signer,omitempty"` + Signer int32 `protobuf:"varint,1,opt,name=signer,proto3" json:"signer,omitempty"` } func (x *BadSigner) Reset() { @@ -9409,11 +9391,11 @@ func (*BadSigner) Descriptor() ([]byte, []int) { return file_signers_proto_rawDescGZIP(), []int{8} } -func (x *BadSigner) GetSigner() []byte { +func (x *BadSigner) GetSigner() int32 { if x != nil { return x.Signer } - return nil + return 0 } type NoSignerOption struct { @@ -9885,7 +9867,7 @@ var file_signers_proto_rawDesc = []byte{ 0x05, 0x69, 0x6e, 0x6e, 0x65, 0x72, 0x3a, 0x0a, 0x82, 0xe7, 0xb0, 0x2a, 0x05, 0x69, 0x6e, 0x6e, 0x65, 0x72, 0x3a, 0x0a, 0x82, 0xe7, 0xb0, 0x2a, 0x05, 0x69, 0x6e, 0x6e, 0x65, 0x72, 0x22, 0x30, 0x0a, 0x09, 0x42, 0x61, 0x64, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x12, 0x16, 0x0a, 0x06, 0x73, - 0x69, 0x67, 0x6e, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x73, 0x69, 0x67, + 0x69, 0x67, 0x6e, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x3a, 0x0b, 0x82, 0xe7, 0xb0, 0x2a, 0x06, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x22, 0x28, 0x0a, 0x0e, 0x4e, 0x6f, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, diff --git a/x/tx/signing/aminojson/aminojson_test.go b/x/tx/signing/aminojson/aminojson_test.go index 0d137906561d..dee071dc5528 100644 --- a/x/tx/signing/aminojson/aminojson_test.go +++ b/x/tx/signing/aminojson/aminojson_test.go @@ -24,7 +24,7 @@ func TestAminoJsonSignMode(t *testing.T) { Msg: &bankv1beta1.MsgSend{ FromAddress: "foo", ToAddress: "bar", - Amount: []*basev1beta1.Coin{{Denom: "demon", Amount: "100"}}, + Amount: []*basev1beta1.Coin{{Denom: "denom", Amount: "100"}}, }, AccNum: 1, AccSeq: 2, diff --git a/x/tx/signing/aminojson/encoder.go b/x/tx/signing/aminojson/encoder.go index 9fe589c0e544..d3e1e75c8bba 100644 --- a/x/tx/signing/aminojson/encoder.go +++ b/x/tx/signing/aminojson/encoder.go @@ -51,7 +51,12 @@ func cosmosDecEncoder(_ *Encoder, v protoreflect.Value, w io.Writer) error { if val == "" { return jsonMarshal(w, "0") } - return jsonMarshal(w, val) + var dec math.LegacyDec + err := dec.Unmarshal([]byte(val)) + if err != nil { + return err + } + return jsonMarshal(w, dec.String()) case []byte: if len(val) == 0 { return jsonMarshal(w, "0") @@ -125,27 +130,40 @@ func keyFieldEncoder(_ *Encoder, msg protoreflect.Message, w io.Writer) error { } type moduleAccountPretty struct { - Address string `json:"address"` - PubKey string `json:"public_key"` AccountNumber uint64 `json:"account_number"` - Sequence uint64 `json:"sequence"` + Address string `json:"address"` Name string `json:"name"` Permissions []string `json:"permissions"` + PubKey string `json:"public_key"` + Sequence uint64 `json:"sequence"` } // moduleAccountEncoder replicates the behavior in // https://github.com/cosmos/cosmos-sdk/blob/41a3dfeced2953beba3a7d11ec798d17ee19f506/x/auth/types/account.go#L230-L254 func moduleAccountEncoder(_ *Encoder, msg protoreflect.Message, w io.Writer) error { - ma := msg.Interface().(*authapi.ModuleAccount) + ma := &authapi.ModuleAccount{} + msgDesc := msg.Descriptor() + if msgDesc.FullName() != ma.ProtoReflect().Descriptor().FullName() { + return errors.New("moduleAccountEncoder: msg not a auth.ModuleAccount") + } + fields := msgDesc.Fields() + pretty := moduleAccountPretty{ - PubKey: "", - Name: ma.Name, - Permissions: ma.Permissions, - } - if ma.BaseAccount != nil { - pretty.Address = ma.BaseAccount.Address - pretty.AccountNumber = ma.BaseAccount.AccountNumber - pretty.Sequence = ma.BaseAccount.Sequence + PubKey: "", + Name: msg.Get(fields.ByName("name")).String(), + } + permissions := msg.Get(fields.ByName("permissions")).List() + for i := 0; i < permissions.Len(); i++ { + pretty.Permissions = append(pretty.Permissions, permissions.Get(i).String()) + } + + if msg.Has(fields.ByName("base_account")) { + baseAccount := msg.Get(fields.ByName("base_account")) + baMsg := baseAccount.Message() + bamdFields := baMsg.Descriptor().Fields() + pretty.Address = baMsg.Get(bamdFields.ByName("address")).String() + pretty.AccountNumber = baMsg.Get(bamdFields.ByName("account_number")).Uint() + pretty.Sequence = baMsg.Get(bamdFields.ByName("sequence")).Uint() } else { pretty.Address = "" pretty.AccountNumber = 0 @@ -166,29 +184,34 @@ func moduleAccountEncoder(_ *Encoder, msg protoreflect.Message, w io.Writer) err // also see: // https://github.com/cosmos/cosmos-sdk/blob/b49f948b36bc991db5be431607b475633aed697e/proto/cosmos/crypto/multisig/keys.proto#L15/ func thresholdStringEncoder(enc *Encoder, msg protoreflect.Message, w io.Writer) error { - pk, ok := msg.Interface().(*multisig.LegacyAminoPubKey) - if !ok { + pk := &multisig.LegacyAminoPubKey{} + msgDesc := msg.Descriptor() + fields := msgDesc.Fields() + if msgDesc.FullName() != pk.ProtoReflect().Descriptor().FullName() { return errors.New("thresholdStringEncoder: msg not a multisig.LegacyAminoPubKey") } - _, err := fmt.Fprintf(w, `{"threshold":"%d","pubkeys":`, pk.Threshold) - if err != nil { - return err - } - if len(pk.PublicKeys) == 0 { - _, err = io.WriteString(w, `[]}`) - return err - } - - fields := msg.Descriptor().Fields() pubkeysField := fields.ByName("public_keys") pubkeys := msg.Get(pubkeysField).List() - err = enc.marshalList(pubkeys, pubkeysField, w) + _, err := io.WriteString(w, `{"pubkeys":`) if err != nil { return err } - _, err = io.WriteString(w, `}`) + if pubkeys.Len() == 0 { + _, err := io.WriteString(w, `[]`) + if err != nil { + return err + } + } else { + err := enc.marshalList(pubkeys, pubkeysField, w) + if err != nil { + return err + } + } + + threshold := fields.ByName("threshold") + _, err = fmt.Fprintf(w, `,"threshold":"%d"}`, msg.Get(threshold).Uint()) return err } diff --git a/x/tx/signing/aminojson/fuzz_test.go b/x/tx/signing/aminojson/fuzz_test.go index e5cbe7ccf3f1..d466921933f5 100644 --- a/x/tx/signing/aminojson/fuzz_test.go +++ b/x/tx/signing/aminojson/fuzz_test.go @@ -29,7 +29,7 @@ func FuzzSignModeGetSignBytes(f *testing.F) { Msg: &bankv1beta1.MsgSend{ FromAddress: "foo", ToAddress: "bar", - Amount: []*basev1beta1.Coin{{Denom: "demon", Amount: "100"}}, + Amount: []*basev1beta1.Coin{{Denom: "denom", Amount: "100"}}, }, AccNum: 1, AccSeq: 2, diff --git a/x/tx/signing/aminojson/internal/testpb/test.proto b/x/tx/signing/aminojson/internal/testpb/test.proto index 0bbb999426e6..421d1815d80e 100644 --- a/x/tx/signing/aminojson/internal/testpb/test.proto +++ b/x/tx/signing/aminojson/internal/testpb/test.proto @@ -32,19 +32,20 @@ message ABitOfEverything { repeated int32 repeated = 6; - string str = 7; - bool bool = 8; - bytes bytes = 9; - int32 i32 = 10; - fixed32 f32 = 11; - uint32 u32 = 12; - sint32 si32 = 13; - sfixed32 sf32 = 14; - int64 i64 = 15; - fixed64 f64 = 16; - uint64 u64 = 17; - sint64 si64 = 18; - sfixed64 sf64 = 19; + string str = 7; + bool bool = 8; + bytes bytes = 9; + int32 i32 = 10; + fixed32 f32 = 11; + uint32 u32 = 12; + sint32 si32 = 13; + sfixed32 sf32 = 14; + int64 i64 = 15; + fixed64 f64 = 16; + uint64 u64 = 17; + sint64 si64 = 18; + sfixed64 sf64 = 19; + bytes pretty_bytes = 20 [(amino.encoding) = "hex"]; // The following types are not tested here because they are treated fundamentally differently in // gogoproto. They are tested fully in /tests/integration/aminojson/aminojson_test.go diff --git a/x/tx/signing/aminojson/internal/testpb/test.pulsar.go b/x/tx/signing/aminojson/internal/testpb/test.pulsar.go index 0adf0b573d60..869176b6bb0e 100644 --- a/x/tx/signing/aminojson/internal/testpb/test.pulsar.go +++ b/x/tx/signing/aminojson/internal/testpb/test.pulsar.go @@ -1755,23 +1755,24 @@ func (x *_ABitOfEverything_6_list) IsValid() bool { } var ( - md_ABitOfEverything protoreflect.MessageDescriptor - fd_ABitOfEverything_message protoreflect.FieldDescriptor - fd_ABitOfEverything_enum protoreflect.FieldDescriptor - fd_ABitOfEverything_repeated protoreflect.FieldDescriptor - fd_ABitOfEverything_str protoreflect.FieldDescriptor - fd_ABitOfEverything_bool protoreflect.FieldDescriptor - fd_ABitOfEverything_bytes protoreflect.FieldDescriptor - fd_ABitOfEverything_i32 protoreflect.FieldDescriptor - fd_ABitOfEverything_f32 protoreflect.FieldDescriptor - fd_ABitOfEverything_u32 protoreflect.FieldDescriptor - fd_ABitOfEverything_si32 protoreflect.FieldDescriptor - fd_ABitOfEverything_sf32 protoreflect.FieldDescriptor - fd_ABitOfEverything_i64 protoreflect.FieldDescriptor - fd_ABitOfEverything_f64 protoreflect.FieldDescriptor - fd_ABitOfEverything_u64 protoreflect.FieldDescriptor - fd_ABitOfEverything_si64 protoreflect.FieldDescriptor - fd_ABitOfEverything_sf64 protoreflect.FieldDescriptor + md_ABitOfEverything protoreflect.MessageDescriptor + fd_ABitOfEverything_message protoreflect.FieldDescriptor + fd_ABitOfEverything_enum protoreflect.FieldDescriptor + fd_ABitOfEverything_repeated protoreflect.FieldDescriptor + fd_ABitOfEverything_str protoreflect.FieldDescriptor + fd_ABitOfEverything_bool protoreflect.FieldDescriptor + fd_ABitOfEverything_bytes protoreflect.FieldDescriptor + fd_ABitOfEverything_i32 protoreflect.FieldDescriptor + fd_ABitOfEverything_f32 protoreflect.FieldDescriptor + fd_ABitOfEverything_u32 protoreflect.FieldDescriptor + fd_ABitOfEverything_si32 protoreflect.FieldDescriptor + fd_ABitOfEverything_sf32 protoreflect.FieldDescriptor + fd_ABitOfEverything_i64 protoreflect.FieldDescriptor + fd_ABitOfEverything_f64 protoreflect.FieldDescriptor + fd_ABitOfEverything_u64 protoreflect.FieldDescriptor + fd_ABitOfEverything_si64 protoreflect.FieldDescriptor + fd_ABitOfEverything_sf64 protoreflect.FieldDescriptor + fd_ABitOfEverything_pretty_bytes protoreflect.FieldDescriptor ) func init() { @@ -1793,6 +1794,7 @@ func init() { fd_ABitOfEverything_u64 = md_ABitOfEverything.Fields().ByName("u64") fd_ABitOfEverything_si64 = md_ABitOfEverything.Fields().ByName("si64") fd_ABitOfEverything_sf64 = md_ABitOfEverything.Fields().ByName("sf64") + fd_ABitOfEverything_pretty_bytes = md_ABitOfEverything.Fields().ByName("pretty_bytes") } var _ protoreflect.Message = (*fastReflection_ABitOfEverything)(nil) @@ -1956,6 +1958,12 @@ func (x *fastReflection_ABitOfEverything) Range(f func(protoreflect.FieldDescrip return } } + if len(x.PrettyBytes) != 0 { + value := protoreflect.ValueOfBytes(x.PrettyBytes) + if !f(fd_ABitOfEverything_pretty_bytes, value) { + return + } + } } // Has reports whether a field is populated. @@ -2003,6 +2011,8 @@ func (x *fastReflection_ABitOfEverything) Has(fd protoreflect.FieldDescriptor) b return x.Si64 != int64(0) case "testpb.ABitOfEverything.sf64": return x.Sf64 != int64(0) + case "testpb.ABitOfEverything.pretty_bytes": + return len(x.PrettyBytes) != 0 default: if fd.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: testpb.ABitOfEverything")) @@ -2051,6 +2061,8 @@ func (x *fastReflection_ABitOfEverything) Clear(fd protoreflect.FieldDescriptor) x.Si64 = int64(0) case "testpb.ABitOfEverything.sf64": x.Sf64 = int64(0) + case "testpb.ABitOfEverything.pretty_bytes": + x.PrettyBytes = nil default: if fd.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: testpb.ABitOfEverything")) @@ -2118,6 +2130,9 @@ func (x *fastReflection_ABitOfEverything) Get(descriptor protoreflect.FieldDescr case "testpb.ABitOfEverything.sf64": value := x.Sf64 return protoreflect.ValueOfInt64(value) + case "testpb.ABitOfEverything.pretty_bytes": + value := x.PrettyBytes + return protoreflect.ValueOfBytes(value) default: if descriptor.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: testpb.ABitOfEverything")) @@ -2172,6 +2187,8 @@ func (x *fastReflection_ABitOfEverything) Set(fd protoreflect.FieldDescriptor, v x.Si64 = value.Int() case "testpb.ABitOfEverything.sf64": x.Sf64 = value.Int() + case "testpb.ABitOfEverything.pretty_bytes": + x.PrettyBytes = value.Bytes() default: if fd.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: testpb.ABitOfEverything")) @@ -2231,6 +2248,8 @@ func (x *fastReflection_ABitOfEverything) Mutable(fd protoreflect.FieldDescripto panic(fmt.Errorf("field si64 of message testpb.ABitOfEverything is not mutable")) case "testpb.ABitOfEverything.sf64": panic(fmt.Errorf("field sf64 of message testpb.ABitOfEverything is not mutable")) + case "testpb.ABitOfEverything.pretty_bytes": + panic(fmt.Errorf("field pretty_bytes of message testpb.ABitOfEverything is not mutable")) default: if fd.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: testpb.ABitOfEverything")) @@ -2278,6 +2297,8 @@ func (x *fastReflection_ABitOfEverything) NewField(fd protoreflect.FieldDescript return protoreflect.ValueOfInt64(int64(0)) case "testpb.ABitOfEverything.sf64": return protoreflect.ValueOfInt64(int64(0)) + case "testpb.ABitOfEverything.pretty_bytes": + return protoreflect.ValueOfBytes(nil) default: if fd.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: testpb.ABitOfEverything")) @@ -2402,6 +2423,10 @@ func (x *fastReflection_ABitOfEverything) ProtoMethods() *protoiface.Methods { if x.Sf64 != 0 { n += 10 } + l = len(x.PrettyBytes) + if l > 0 { + n += 2 + l + runtime.Sov(uint64(l)) + } if x.unknownFields != nil { n += len(x.unknownFields) } @@ -2431,6 +2456,15 @@ func (x *fastReflection_ABitOfEverything) ProtoMethods() *protoiface.Methods { i -= len(x.unknownFields) copy(dAtA[i:], x.unknownFields) } + if len(x.PrettyBytes) > 0 { + i -= len(x.PrettyBytes) + copy(dAtA[i:], x.PrettyBytes) + i = runtime.EncodeVarint(dAtA, i, uint64(len(x.PrettyBytes))) + i-- + dAtA[i] = 0x1 + i-- + dAtA[i] = 0xa2 + } if x.Sf64 != 0 { i -= 8 binary.LittleEndian.PutUint64(dAtA[i:], uint64(x.Sf64)) @@ -2981,6 +3015,40 @@ func (x *fastReflection_ABitOfEverything) ProtoMethods() *protoiface.Methods { } x.Sf64 = int64(binary.LittleEndian.Uint64(dAtA[iNdEx:])) iNdEx += 8 + case 20: + if wireType != 2 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field PrettyBytes", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow + } + if iNdEx >= l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + if postIndex > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + x.PrettyBytes = append(x.PrettyBytes[:0], dAtA[iNdEx:postIndex]...) + if x.PrettyBytes == nil { + x.PrettyBytes = []byte{} + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := runtime.Skip(dAtA[iNdEx:]) @@ -4178,22 +4246,23 @@ type ABitOfEverything struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Message *NestedMessage `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"` - Enum AnEnum `protobuf:"varint,2,opt,name=enum,proto3,enum=testpb.AnEnum" json:"enum,omitempty"` - Repeated []int32 `protobuf:"varint,6,rep,packed,name=repeated,proto3" json:"repeated,omitempty"` - Str string `protobuf:"bytes,7,opt,name=str,proto3" json:"str,omitempty"` - Bool bool `protobuf:"varint,8,opt,name=bool,proto3" json:"bool,omitempty"` - Bytes []byte `protobuf:"bytes,9,opt,name=bytes,proto3" json:"bytes,omitempty"` - I32 int32 `protobuf:"varint,10,opt,name=i32,proto3" json:"i32,omitempty"` - F32 uint32 `protobuf:"fixed32,11,opt,name=f32,proto3" json:"f32,omitempty"` - U32 uint32 `protobuf:"varint,12,opt,name=u32,proto3" json:"u32,omitempty"` - Si32 int32 `protobuf:"zigzag32,13,opt,name=si32,proto3" json:"si32,omitempty"` - Sf32 int32 `protobuf:"fixed32,14,opt,name=sf32,proto3" json:"sf32,omitempty"` - I64 int64 `protobuf:"varint,15,opt,name=i64,proto3" json:"i64,omitempty"` - F64 uint64 `protobuf:"fixed64,16,opt,name=f64,proto3" json:"f64,omitempty"` - U64 uint64 `protobuf:"varint,17,opt,name=u64,proto3" json:"u64,omitempty"` - Si64 int64 `protobuf:"zigzag64,18,opt,name=si64,proto3" json:"si64,omitempty"` - Sf64 int64 `protobuf:"fixed64,19,opt,name=sf64,proto3" json:"sf64,omitempty"` + Message *NestedMessage `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"` + Enum AnEnum `protobuf:"varint,2,opt,name=enum,proto3,enum=testpb.AnEnum" json:"enum,omitempty"` + Repeated []int32 `protobuf:"varint,6,rep,packed,name=repeated,proto3" json:"repeated,omitempty"` + Str string `protobuf:"bytes,7,opt,name=str,proto3" json:"str,omitempty"` + Bool bool `protobuf:"varint,8,opt,name=bool,proto3" json:"bool,omitempty"` + Bytes []byte `protobuf:"bytes,9,opt,name=bytes,proto3" json:"bytes,omitempty"` + I32 int32 `protobuf:"varint,10,opt,name=i32,proto3" json:"i32,omitempty"` + F32 uint32 `protobuf:"fixed32,11,opt,name=f32,proto3" json:"f32,omitempty"` + U32 uint32 `protobuf:"varint,12,opt,name=u32,proto3" json:"u32,omitempty"` + Si32 int32 `protobuf:"zigzag32,13,opt,name=si32,proto3" json:"si32,omitempty"` + Sf32 int32 `protobuf:"fixed32,14,opt,name=sf32,proto3" json:"sf32,omitempty"` + I64 int64 `protobuf:"varint,15,opt,name=i64,proto3" json:"i64,omitempty"` + F64 uint64 `protobuf:"fixed64,16,opt,name=f64,proto3" json:"f64,omitempty"` + U64 uint64 `protobuf:"varint,17,opt,name=u64,proto3" json:"u64,omitempty"` + Si64 int64 `protobuf:"zigzag64,18,opt,name=si64,proto3" json:"si64,omitempty"` + Sf64 int64 `protobuf:"fixed64,19,opt,name=sf64,proto3" json:"sf64,omitempty"` + PrettyBytes []byte `protobuf:"bytes,20,opt,name=pretty_bytes,json=prettyBytes,proto3" json:"pretty_bytes,omitempty"` } func (x *ABitOfEverything) Reset() { @@ -4328,6 +4397,13 @@ func (x *ABitOfEverything) GetSf64() int64 { return 0 } +func (x *ABitOfEverything) GetPrettyBytes() []byte { + if x != nil { + return x.PrettyBytes + } + return nil +} + type Duration struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -4450,7 +4526,7 @@ var file_testpb_test_proto_rawDesc = []byte{ 0x09, 0x57, 0x69, 0x74, 0x68, 0x41, 0x4a, 0x73, 0x6f, 0x6e, 0x12, 0x28, 0x0a, 0x06, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x31, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x10, 0x9a, 0xe7, 0xb0, 0x2a, 0x0b, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x6a, 0x73, 0x6f, 0x6e, 0x52, 0x06, 0x66, 0x69, - 0x65, 0x6c, 0x64, 0x31, 0x22, 0x92, 0x03, 0x0a, 0x10, 0x41, 0x42, 0x69, 0x74, 0x4f, 0x66, 0x45, + 0x65, 0x6c, 0x64, 0x31, 0x22, 0xbf, 0x03, 0x0a, 0x10, 0x41, 0x42, 0x69, 0x74, 0x4f, 0x66, 0x45, 0x76, 0x65, 0x72, 0x79, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x12, 0x2f, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x70, 0x62, 0x2e, 0x4e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, @@ -4474,32 +4550,35 @@ var file_testpb_test_proto_rawDesc = []byte{ 0x11, 0x20, 0x01, 0x28, 0x04, 0x52, 0x03, 0x75, 0x36, 0x34, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x69, 0x36, 0x34, 0x18, 0x12, 0x20, 0x01, 0x28, 0x12, 0x52, 0x04, 0x73, 0x69, 0x36, 0x34, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x66, 0x36, 0x34, 0x18, 0x13, 0x20, 0x01, 0x28, 0x10, 0x52, 0x04, 0x73, 0x66, - 0x36, 0x34, 0x3a, 0x15, 0x8a, 0xe7, 0xb0, 0x2a, 0x10, 0x41, 0x42, 0x69, 0x74, 0x4f, 0x66, 0x45, - 0x76, 0x65, 0x72, 0x79, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x22, 0x7b, 0x0a, 0x08, 0x44, 0x75, 0x72, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x35, 0x0a, 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x52, 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x38, 0x0a, 0x09, - 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x74, 0x69, 0x6d, - 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x22, 0x47, 0x0a, 0x0d, 0x4e, 0x65, 0x73, 0x74, 0x65, 0x64, - 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x66, 0x6f, 0x6f, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x66, 0x6f, 0x6f, 0x12, 0x10, 0x0a, 0x03, 0x62, 0x61, 0x72, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x62, 0x61, 0x72, 0x3a, 0x12, 0x8a, 0xe7, 0xb0, - 0x2a, 0x0d, 0x4e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2a, - 0x29, 0x0a, 0x06, 0x41, 0x6e, 0x45, 0x6e, 0x75, 0x6d, 0x12, 0x0d, 0x0a, 0x09, 0x55, 0x4e, 0x44, - 0x45, 0x46, 0x49, 0x4e, 0x45, 0x44, 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03, 0x4f, 0x4e, 0x45, 0x10, - 0x01, 0x12, 0x07, 0x0a, 0x03, 0x54, 0x57, 0x4f, 0x10, 0x02, 0x42, 0x83, 0x01, 0x0a, 0x0a, 0x63, - 0x6f, 0x6d, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x70, 0x62, 0x42, 0x09, 0x54, 0x65, 0x73, 0x74, 0x50, - 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x32, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x73, 0x64, - 0x6b, 0x2e, 0x69, 0x6f, 0x2f, 0x78, 0x2f, 0x74, 0x78, 0x2f, 0x61, 0x6d, 0x69, 0x6e, 0x6f, 0x6a, - 0x73, 0x6f, 0x6e, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x74, 0x65, 0x73, - 0x74, 0x70, 0x62, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x70, 0x62, 0xa2, 0x02, 0x03, 0x54, 0x58, 0x58, - 0xaa, 0x02, 0x06, 0x54, 0x65, 0x73, 0x74, 0x70, 0x62, 0xca, 0x02, 0x06, 0x54, 0x65, 0x73, 0x74, - 0x70, 0x62, 0xe2, 0x02, 0x12, 0x54, 0x65, 0x73, 0x74, 0x70, 0x62, 0x5c, 0x47, 0x50, 0x42, 0x4d, - 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x06, 0x54, 0x65, 0x73, 0x74, 0x70, 0x62, - 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x36, 0x34, 0x12, 0x2b, 0x0a, 0x0c, 0x70, 0x72, 0x65, 0x74, 0x74, 0x79, 0x5f, 0x62, 0x79, 0x74, + 0x65, 0x73, 0x18, 0x14, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x08, 0x9a, 0xe7, 0xb0, 0x2a, 0x03, 0x68, + 0x65, 0x78, 0x52, 0x0b, 0x70, 0x72, 0x65, 0x74, 0x74, 0x79, 0x42, 0x79, 0x74, 0x65, 0x73, 0x3a, + 0x15, 0x8a, 0xe7, 0xb0, 0x2a, 0x10, 0x41, 0x42, 0x69, 0x74, 0x4f, 0x66, 0x45, 0x76, 0x65, 0x72, + 0x79, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x22, 0x7b, 0x0a, 0x08, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x12, 0x35, 0x0a, 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, + 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x38, 0x0a, 0x09, 0x74, 0x69, 0x6d, + 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, + 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, + 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, + 0x61, 0x6d, 0x70, 0x22, 0x47, 0x0a, 0x0d, 0x4e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x4d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x66, 0x6f, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x03, 0x66, 0x6f, 0x6f, 0x12, 0x10, 0x0a, 0x03, 0x62, 0x61, 0x72, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x05, 0x52, 0x03, 0x62, 0x61, 0x72, 0x3a, 0x12, 0x8a, 0xe7, 0xb0, 0x2a, 0x0d, 0x4e, + 0x65, 0x73, 0x74, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2a, 0x29, 0x0a, 0x06, + 0x41, 0x6e, 0x45, 0x6e, 0x75, 0x6d, 0x12, 0x0d, 0x0a, 0x09, 0x55, 0x4e, 0x44, 0x45, 0x46, 0x49, + 0x4e, 0x45, 0x44, 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03, 0x4f, 0x4e, 0x45, 0x10, 0x01, 0x12, 0x07, + 0x0a, 0x03, 0x54, 0x57, 0x4f, 0x10, 0x02, 0x42, 0x83, 0x01, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x2e, + 0x74, 0x65, 0x73, 0x74, 0x70, 0x62, 0x42, 0x09, 0x54, 0x65, 0x73, 0x74, 0x50, 0x72, 0x6f, 0x74, + 0x6f, 0x50, 0x01, 0x5a, 0x32, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x73, 0x64, 0x6b, 0x2e, 0x69, + 0x6f, 0x2f, 0x78, 0x2f, 0x74, 0x78, 0x2f, 0x61, 0x6d, 0x69, 0x6e, 0x6f, 0x6a, 0x73, 0x6f, 0x6e, + 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x70, 0x62, + 0x2f, 0x74, 0x65, 0x73, 0x74, 0x70, 0x62, 0xa2, 0x02, 0x03, 0x54, 0x58, 0x58, 0xaa, 0x02, 0x06, + 0x54, 0x65, 0x73, 0x74, 0x70, 0x62, 0xca, 0x02, 0x06, 0x54, 0x65, 0x73, 0x74, 0x70, 0x62, 0xe2, + 0x02, 0x12, 0x54, 0x65, 0x73, 0x74, 0x70, 0x62, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, + 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x06, 0x54, 0x65, 0x73, 0x74, 0x70, 0x62, 0x62, 0x06, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/x/tx/signing/aminojson/json_marshal.go b/x/tx/signing/aminojson/json_marshal.go index f276cb39d23e..52defcca6357 100644 --- a/x/tx/signing/aminojson/json_marshal.go +++ b/x/tx/signing/aminojson/json_marshal.go @@ -32,6 +32,10 @@ type EncoderOptions struct { // EnumAsString when set will encode enums as strings instead of integers. // Caution: Enabling this option produce different sign bytes. EnumAsString bool + // AminoNameAsTypeURL when set will use the amino name as the type URL in the JSON output. + // It is useful when using the Amino JSON encoder for non Amino purposes, + // such as JSON RPC. + AminoNameAsTypeURL bool // TypeResolver is used to resolve protobuf message types by TypeURL when marshaling any packed messages. TypeResolver signing.TypeResolver // FileResolver is used to resolve protobuf file descriptors TypeURL when TypeResolver fails. @@ -50,6 +54,7 @@ type Encoder struct { doNotSortFields bool indent string enumsAsString bool + aminoNameAsTypeURL bool } // NewEncoder returns a new Encoder capable of serializing protobuf messages to JSON using the Amino JSON encoding @@ -80,11 +85,12 @@ func NewEncoder(options EncoderOptions) Encoder { "google.protobuf.Duration": marshalDuration, "google.protobuf.Any": marshalAny, }, - fileResolver: options.FileResolver, - typeResolver: options.TypeResolver, - doNotSortFields: options.DoNotSortFields, - indent: options.Indent, - enumsAsString: options.EnumAsString, + fileResolver: options.FileResolver, + typeResolver: options.TypeResolver, + doNotSortFields: options.DoNotSortFields, + indent: options.Indent, + enumsAsString: options.EnumAsString, + aminoNameAsTypeURL: options.AminoNameAsTypeURL, } return enc } @@ -187,9 +193,17 @@ func (enc Encoder) beginMarshal(msg protoreflect.Message, writer io.Writer, isAn ) if isAny { - name, named = getMessageAminoNameAny(msg), true + if enc.aminoNameAsTypeURL { + name, named = getMessageTypeURL(msg), true + } else { + name, named = getMessageAminoNameAny(msg), true + } } else { name, named = getMessageAminoName(msg) + if enc.aminoNameAsTypeURL { + // do not override named + name = getMessageTypeURL(msg) + } } if named { diff --git a/x/tx/signing/aminojson/json_marshal_test.go b/x/tx/signing/aminojson/json_marshal_test.go index a51b83bb49da..b2a4ddd77e42 100644 --- a/x/tx/signing/aminojson/json_marshal_test.go +++ b/x/tx/signing/aminojson/json_marshal_test.go @@ -1,6 +1,7 @@ package aminojson_test import ( + "crypto/sha256" "encoding/json" "errors" "fmt" @@ -355,3 +356,92 @@ func TestEnumAsString(t *testing.T) { } }`, string(bz)) } + +func TestAminoNameAsTypeURL(t *testing.T) { + encoder := aminojson.NewEncoder(aminojson.EncoderOptions{Indent: " ", AminoNameAsTypeURL: true}) + + msg := &testpb.ABitOfEverything{ + Message: &testpb.NestedMessage{ + Foo: "test", + Bar: 0, // this is the default value and should be omitted from output + }, + Enum: testpb.AnEnum_ONE, + Repeated: []int32{3, -7, 2, 6, 4}, + Str: `abcxyz"foo"def`, + Bool: true, + Bytes: []byte{0, 1, 2, 3}, + I32: -15, + F32: 1001, + U32: 1200, + Si32: -376, + Sf32: -1000, + I64: 14578294827584932, + F64: 9572348124213523654, + U64: 4759492485, + Si64: -59268425823934, + Sf64: -659101379604211154, + } + + bz, err := encoder.Marshal(msg) + require.NoError(t, err) + fmt.Println(string(bz)) + require.Equal(t, `{ + "type": "/testpb.ABitOfEverything", + "value": { + "bool": true, + "bytes": "AAECAw==", + "enum": 1, + "f32": 1001, + "f64": "9572348124213523654", + "i32": -15, + "i64": "14578294827584932", + "message": { + "foo": "test" + }, + "repeated": [ + 3, + -7, + 2, + 6, + 4 + ], + "sf32": -1000, + "sf64": "-659101379604211154", + "si32": -376, + "si64": "-59268425823934", + "str": "abcxyz\"foo\"def", + "u32": 1200, + "u64": "4759492485" + } +}`, string(bz)) +} + +func TestCustomBytesEncoder(t *testing.T) { + cdc := amino.NewCodec() + cdc.RegisterConcrete(&testpb.ABitOfEverything{}, "ABitOfEverything", nil) + encoder := aminojson.NewEncoder(aminojson.EncoderOptions{}) + + bz := sha256.Sum256([]byte("test")) + + msg := &testpb.ABitOfEverything{ + Bytes: bz[:], + PrettyBytes: bz[:], + } + + legacyJSON, err := cdc.MarshalJSON(msg) + require.NoError(t, err) + aminoJSON, err := encoder.Marshal(msg) + require.NoError(t, err) + require.Equal(t, string(legacyJSON), string(aminoJSON)) + + encoder.DefineFieldEncoding( + "hex", + func(enc *aminojson.Encoder, v protoreflect.Value, w io.Writer) error { + _, err := fmt.Fprintf(w, "\"%x\"", v.Bytes()) + return err + }) + aminoJSON, err = encoder.Marshal(msg) + require.NoError(t, err) + require.NotEqual(t, string(legacyJSON), string(aminoJSON)) + t.Logf("hex encoded bytes: %s", string(aminoJSON)) +} diff --git a/x/tx/signing/aminojson/options.go b/x/tx/signing/aminojson/options.go index 0eecedb88731..cf9110aef3ae 100644 --- a/x/tx/signing/aminojson/options.go +++ b/x/tx/signing/aminojson/options.go @@ -25,7 +25,6 @@ func getMessageAminoName(msg protoreflect.Message) (string, bool) { // getMessageAminoName returns the amino name of a message if it has been set by the `amino.name` option. // If the message does not have an amino name, then it returns the msg url. -// If it cannot get the msg url, then it returns false. func getMessageAminoNameAny(msg protoreflect.Message) string { messageOptions := msg.Descriptor().Options() if proto.HasExtension(messageOptions, amino.E_Name) { @@ -33,6 +32,11 @@ func getMessageAminoNameAny(msg protoreflect.Message) string { return name.(string) } + return getMessageTypeURL(msg) +} + +// getMessageTypeURL returns the msg url. +func getMessageTypeURL(msg protoreflect.Message) string { msgURL := "/" + string(msg.Descriptor().FullName()) if msgURL != "/" { return msgURL diff --git a/x/tx/signing/context.go b/x/tx/signing/context.go index f44be0118cca..d02be6d12523 100644 --- a/x/tx/signing/context.go +++ b/x/tx/signing/context.go @@ -301,6 +301,11 @@ func (c *Context) makeGetSignersFunc(descriptor protoreflect.MessageDescriptor) } return arr, nil } + case protoreflect.BytesKind: + fieldGetters[i] = func(msg proto.Message, arr [][]byte) ([][]byte, error) { + addrBz := msg.ProtoReflect().Get(field).Bytes() + return append(arr, addrBz), nil + } default: return nil, fmt.Errorf("unexpected field type %s for field %s in message %s", field.Kind(), fieldName, descriptor.FullName()) } diff --git a/x/tx/signing/textual/any_test.go b/x/tx/signing/textual/any_test.go index da64acf0df79..0bcce5988151 100644 --- a/x/tx/signing/textual/any_test.go +++ b/x/tx/signing/textual/any_test.go @@ -88,7 +88,6 @@ func TestDynamicpb(t *testing.T) { } for _, tc := range testcases { - tc := tc t.Run(tc.name, func(t *testing.T) { any, err := anyutil.New(tc.msg) require.NoError(t, err) diff --git a/x/tx/signing/textual/dec_test.go b/x/tx/signing/textual/dec_test.go index f8c7b3ebe2f4..152e2b71619e 100644 --- a/x/tx/signing/textual/dec_test.go +++ b/x/tx/signing/textual/dec_test.go @@ -27,7 +27,6 @@ func TestDecJSONTestcases(t *testing.T) { require.NoError(t, err) for _, tc := range testcases { - tc := tc t.Run(tc[0], func(t *testing.T) { r, err := textual.GetFieldValueRenderer(fieldDescriptorFromName("SDKDEC")) require.NoError(t, err) diff --git a/x/tx/signing/textual/handler_test.go b/x/tx/signing/textual/handler_test.go index 70c2ea124a9f..13e15b981845 100644 --- a/x/tx/signing/textual/handler_test.go +++ b/x/tx/signing/textual/handler_test.go @@ -32,7 +32,6 @@ func TestDispatcher(t *testing.T) { } for _, tc := range testcases { - tc := tc t.Run(tc.name, func(t *testing.T) { textual, err := textual.NewSignModeHandler(textual.SignModeOptions{CoinMetadataQuerier: EmptyCoinMetadataQuerier}) require.NoError(t, err) diff --git a/x/upgrade/README.md b/x/upgrade/README.md index 81534d422694..9e9c41e8ccc9 100644 --- a/x/upgrade/README.md +++ b/x/upgrade/README.md @@ -106,7 +106,7 @@ the `Plan`, which targets a specific `Handler`, is persisted and scheduled. The upgrade can be delayed or hastened by updating the `Plan.Height` in a new proposal. ```protobuf reference -https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/upgrade/v1beta1/tx.proto#L29-L41 +https://github.com/cosmos/cosmos-sdk/blob/v0.52.0-beta.1/x/upgrade/proto/cosmos/upgrade/v1beta1/tx.proto#L29-L40 ``` #### Cancelling Upgrade Proposals @@ -118,7 +118,7 @@ Of course this requires that the upgrade was known to be a bad idea well before upgrade itself, to allow time for a vote. ```protobuf reference -https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/upgrade/v1beta1/tx.proto#L48-L57 +https://github.com/cosmos/cosmos-sdk/blob/v0.52.0-beta.1/x/upgrade/proto/cosmos/upgrade/v1beta1/tx.proto#L47-L55 ``` If such a possibility is desired, the upgrade height is to be @@ -315,6 +315,28 @@ time: "0001-01-01T00:00:00Z" upgraded_client_state: null ``` +##### authority + +The `authority` command allows users to query the address that is authorized to submit upgrade proposals. + +```bash +simd query upgrade authority [flags] +``` + +This command returns the bech32-encoded address of the account that has the authority to submit upgrade proposals. + +Example: + +```bash +simd query upgrade authority +``` + +Example Output: + +```bash +cosmos10d07y265gmmuvt4z0w9aw880jnsr700j6zn9kn +``` + #### Transactions The upgrade module supports the following transactions: @@ -326,10 +348,10 @@ simd tx upgrade software-upgrade v2 --title="Test Proposal" --summary="testing" --upgrade-info '{ "binaries": { "linux/amd64":"https://example.com/simd.zip?checksum=sha256:aec070645fe53ee3b3763059376134f058cc337247c978add178b6ccdfb0019f" } }' --from cosmos1.. ``` -* `cancel-software-upgrade` - cancels a previously submitted upgrade proposal: +* `cancel-upgrade-proposal` - cancels a previously submitted upgrade proposal: ```bash -simd tx upgrade cancel-software-upgrade --title="Test Proposal" --summary="testing" --deposit="100000000stake" --from cosmos1.. +simd tx upgrade cancel-upgrade-proposal --title="Test Proposal" --summary="testing" --deposit="100000000stake" --from cosmos1.. ``` ### REST @@ -467,6 +489,28 @@ Example Output: } ``` +#### Authority + +`Authority` queries the address that is authorized to submit upgrade proposals. + +```bash +/cosmos/upgrade/v1beta1/authority +``` + +Example: + +```bash +curl -X GET "http://localhost:1317/cosmos/upgrade/v1beta1/authority" -H "accept: application/json" +``` + +Example Output: + +```json +{ +"address": "cosmos10d07y265gmmuvt4z0w9aw880jnsr700j6zn9kn" +} +``` + ### gRPC A user can query the `upgrade` module using gRPC endpoints. @@ -507,7 +551,7 @@ cosmos.upgrade.v1beta1.Query/CurrentPlan Example: ```bash -grpcurl -plaintext localhost:9090 cosmos.slashing.v1beta1.Query/CurrentPlan +grpcurl -plaintext localhost:9090 cosmos.upgrade.v1beta1.Query/CurrentPlan ``` Example Output: @@ -529,7 +573,7 @@ cosmos.upgrade.v1beta1.Query/ModuleVersions Example: ```bash -grpcurl -plaintext localhost:9090 cosmos.slashing.v1beta1.Query/ModuleVersions +grpcurl -plaintext localhost:9090 cosmos.upgrade.v1beta1.Query/ModuleVersions ``` Example Output: @@ -605,6 +649,28 @@ Example Output: } ``` +#### Authority + +`Authority` queries the address that is authorized to submit upgrade proposals. + +```bash +cosmos.upgrade.v1beta1.Query/Authority +``` + +Example: + +```bash +grpcurl -plaintext localhost:9090 cosmos.upgrade.v1beta1.Query/Authority +``` + +Example Output: + +```json +{ + "address": "cosmos10d07y265gmmuvt4z0w9aw880jnsr700j6zn9kn" +} +``` + ## Resources A list of (external) resources to learn more about the `x/upgrade` module. diff --git a/x/upgrade/client/cli/tx.go b/x/upgrade/client/cli/tx.go index c817fcba9020..7f95184f3751 100644 --- a/x/upgrade/client/cli/tx.go +++ b/x/upgrade/client/cli/tx.go @@ -50,7 +50,7 @@ func NewCmdSubmitUpgradeProposal() *cobra.Command { Short: "Submit a software upgrade proposal", Long: "Submit a software upgrade along with an initial deposit.\n" + "Please specify a unique name and height for the upgrade to take effect.\n" + - "You may include info to reference a binary download link, in a format compatible with: https://docs.cosmos.network/main/tooling/cosmovisor", + "You may include info to reference a binary download link, in a format compatible with: https://docs.cosmos.network/main/build/tooling/cosmovisor", RunE: func(cmd *cobra.Command, args []string) error { clientCtx, err := client.GetClientTxContext(cmd) if err != nil { diff --git a/x/upgrade/go.mod b/x/upgrade/go.mod index 2be842e1dc9b..6505f6b4b02a 100644 --- a/x/upgrade/go.mod +++ b/x/upgrade/go.mod @@ -3,9 +3,9 @@ module cosmossdk.io/x/upgrade go 1.23.1 require ( - cosmossdk.io/api v0.7.5 - cosmossdk.io/core v1.0.0-alpha.2 - cosmossdk.io/core/testing v0.0.0-00010101000000-000000000000 + cosmossdk.io/api v0.7.6 + cosmossdk.io/core v1.0.0-alpha.4 + cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29 cosmossdk.io/depinject v1.0.0 cosmossdk.io/errors v1.0.1 cosmossdk.io/log v1.4.1 @@ -27,7 +27,7 @@ require ( github.com/spf13/pflag v1.0.5 github.com/stretchr/testify v1.9.0 google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 - google.golang.org/grpc v1.66.2 + google.golang.org/grpc v1.67.1 google.golang.org/protobuf v1.34.2 ) @@ -42,7 +42,7 @@ require ( cloud.google.com/go/storage v1.43.0 // indirect cosmossdk.io/collections v0.4.0 // indirect cosmossdk.io/math v1.3.0 // indirect - cosmossdk.io/schema v0.2.0 // indirect + cosmossdk.io/schema v0.3.1-0.20240930054013-7c6e0388a3f9 // indirect cosmossdk.io/x/bank v0.0.0-20240226161501-23359a0b6d91 // indirect cosmossdk.io/x/staking v0.0.0-00010101000000-000000000000 // indirect cosmossdk.io/x/tx v0.13.3 // indirect @@ -119,7 +119,7 @@ require ( github.com/hashicorp/hcl v1.0.0 // indirect github.com/hashicorp/yamux v0.1.1 // indirect github.com/hdevalence/ed25519consensus v0.2.0 // indirect - github.com/huandu/skiplist v1.2.0 // indirect + github.com/huandu/skiplist v1.2.1 // indirect github.com/iancoleman/strcase v0.3.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect @@ -145,9 +145,9 @@ require ( github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/client_golang v1.20.3 // indirect + github.com/prometheus/client_golang v1.20.4 // indirect github.com/prometheus/client_model v0.6.1 // indirect - github.com/prometheus/common v0.59.1 // indirect + github.com/prometheus/common v0.60.0 // indirect github.com/prometheus/procfs v0.15.1 // indirect github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect github.com/rogpeppe/go-internal v1.12.0 // indirect @@ -181,7 +181,7 @@ require ( golang.org/x/exp v0.0.0-20240531132922-fd00a4e0eefc // indirect golang.org/x/mod v0.17.0 // indirect golang.org/x/net v0.29.0 // indirect - golang.org/x/oauth2 v0.22.0 // indirect + golang.org/x/oauth2 v0.23.0 // indirect golang.org/x/sync v0.8.0 // indirect golang.org/x/sys v0.25.0 // indirect golang.org/x/term v0.24.0 // indirect @@ -190,7 +190,7 @@ require ( golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect google.golang.org/api v0.192.0 // indirect google.golang.org/genproto v0.0.0-20240814211410-ddb44dafa142 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect gotest.tools/v3 v3.5.1 // indirect @@ -202,7 +202,6 @@ replace github.com/cosmos/cosmos-sdk => ../../. replace ( cosmossdk.io/api => ../../api - cosmossdk.io/core/testing => ../../core/testing cosmossdk.io/store => ../../store cosmossdk.io/x/bank => ../bank cosmossdk.io/x/gov => ../gov diff --git a/x/upgrade/go.sum b/x/upgrade/go.sum index 2f1b0306c453..257f52f8aca0 100644 --- a/x/upgrade/go.sum +++ b/x/upgrade/go.sum @@ -194,8 +194,10 @@ cloud.google.com/go/workflows v1.6.0/go.mod h1:6t9F5h/unJz41YqfBmqSASJSXccBLtD1V cloud.google.com/go/workflows v1.7.0/go.mod h1:JhSrZuVZWuiDfKEFxU0/F1PQjmpnpcoISEXH2bcHC3M= cosmossdk.io/collections v0.4.0 h1:PFmwj2W8szgpD5nOd8GWH6AbYNi1f2J6akWXJ7P5t9s= cosmossdk.io/collections v0.4.0/go.mod h1:oa5lUING2dP+gdDquow+QjlF45eL1t4TJDypgGd+tv0= -cosmossdk.io/core v1.0.0-alpha.2 h1:epU0Xwces4Rgl5bMhHHkXGaGDcyucNGlC/JDH+Suckg= -cosmossdk.io/core v1.0.0-alpha.2/go.mod h1:abgLjeFLhtuKIYZWSPlVUgQBrKObO7ULV35KYfexE90= +cosmossdk.io/core v1.0.0-alpha.4 h1:9iuroT9ejDYETCsGkzkvs/wAY/5UFl7nCIINFRxyMJY= +cosmossdk.io/core v1.0.0-alpha.4/go.mod h1:3u9cWq1FAVtiiCrDPpo4LhR+9V6k/ycSG4/Y/tREWCY= +cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29 h1:NxxUo0GMJUbIuVg0R70e3cbn9eFTEuMr7ev1AFvypdY= +cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29/go.mod h1:8s2tPeJtSiQuoyPmr2Ag7meikonISO4Fv4MoO8+ORrs= cosmossdk.io/depinject v1.0.0 h1:dQaTu6+O6askNXO06+jyeUAnF2/ssKwrrszP9t5q050= cosmossdk.io/depinject v1.0.0/go.mod h1:zxK/h3HgHoA/eJVtiSsoaRaRA2D5U4cJ5thIG4ssbB8= cosmossdk.io/errors v1.0.1 h1:bzu+Kcr0kS/1DuPBtUFdWjzLqyUuCiyHjyJB6srBV/0= @@ -204,8 +206,8 @@ cosmossdk.io/log v1.4.1 h1:wKdjfDRbDyZRuWa8M+9nuvpVYxrEOwbD/CA8hvhU8QM= cosmossdk.io/log v1.4.1/go.mod h1:k08v0Pyq+gCP6phvdI6RCGhLf/r425UT6Rk/m+o74rU= cosmossdk.io/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE= cosmossdk.io/math v1.3.0/go.mod h1:vnRTxewy+M7BtXBNFybkuhSH4WfedVAAnERHgVFhp3k= -cosmossdk.io/schema v0.2.0 h1:UH5CR1DqUq8yP+5Np8PbvG4YX0zAUsTN2Qk6yThmfMk= -cosmossdk.io/schema v0.2.0/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= +cosmossdk.io/schema v0.3.1-0.20240930054013-7c6e0388a3f9 h1:DmOoS/1PeY6Ih0hAVlJ69kLMUrLV+TCbfICrZtB1vdU= +cosmossdk.io/schema v0.3.1-0.20240930054013-7c6e0388a3f9/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= cosmossdk.io/x/protocolpool v0.0.0-20230925135524-a1bc045b3190 h1:XQJj9Dv9Gtze0l2TF79BU5lkP6MkUveTUuKICmxoz+o= cosmossdk.io/x/protocolpool v0.0.0-20230925135524-a1bc045b3190/go.mod h1:7WUGupOvmlHJoIMBz1JbObQxeo6/TDiuDBxmtod8HRg= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= @@ -585,8 +587,8 @@ github.com/hdevalence/ed25519consensus v0.2.0/go.mod h1:w3BHWjwJbFU29IRHL1Iqkw3s github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/huandu/go-assert v1.1.5 h1:fjemmA7sSfYHJD7CUqs9qTwwfdNAx7/j2/ZlHXzNB3c= github.com/huandu/go-assert v1.1.5/go.mod h1:yOLvuqZwmcHIC5rIzrBhT7D3Q9c3GFnd0JrPVhn/06U= -github.com/huandu/skiplist v1.2.0 h1:gox56QD77HzSC0w+Ws3MH3iie755GBJU1OER3h5VsYw= -github.com/huandu/skiplist v1.2.0/go.mod h1:7v3iFjLcSAzO4fN5B8dvebvo/qsfumiLiDXMrPiHF9w= +github.com/huandu/skiplist v1.2.1 h1:dTi93MgjwErA/8idWTzIw4Y1kZsMWx35fmI2c8Rij7w= +github.com/huandu/skiplist v1.2.1/go.mod h1:7v3iFjLcSAzO4fN5B8dvebvo/qsfumiLiDXMrPiHF9w= github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI= github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= @@ -710,8 +712,8 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= -github.com/prometheus/client_golang v1.20.3 h1:oPksm4K8B+Vt35tUhw6GbSNSgVlVSBH0qELP/7u83l4= -github.com/prometheus/client_golang v1.20.3/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_golang v1.20.4 h1:Tgh3Yr67PaOv/uTqloMsCEdeuFTatm5zIq5+qNN23vI= +github.com/prometheus/client_golang v1.20.4/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -720,8 +722,8 @@ github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= -github.com/prometheus/common v0.59.1 h1:LXb1quJHWm1P6wq/U824uxYi4Sg0oGvNeUm1z5dJoX0= -github.com/prometheus/common v0.59.1/go.mod h1:GpWM7dewqmVYcd7SmRaiWVe9SSqjf0UrwnYnpEZNuT0= +github.com/prometheus/common v0.60.0 h1:+V9PAREWNvJMAuJ1x1BaWl9dewMW4YrHZQbx0sJNllA= +github.com/prometheus/common v0.60.0/go.mod h1:h0LYf1R1deLSKtD4Vdg8gy4RuOvENW2J/h19V5NADQw= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/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= @@ -970,8 +972,8 @@ golang.org/x/oauth2 v0.0.0-20220822191816-0ebed06d0094/go.mod h1:h4gKUeWbJ4rQPri golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= golang.org/x/oauth2 v0.1.0/go.mod h1:G9FE4dLTsbXUu90h/Pf85g4w1D+SSAgR+q46nJZ8M4A= -golang.org/x/oauth2 v0.22.0 h1:BzDx2FehcG7jJwgWLELCdmLuxk2i+x9UDpSiss2u0ZA= -golang.org/x/oauth2 v0.22.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/oauth2 v0.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs= +golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= 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= @@ -1325,8 +1327,8 @@ google.golang.org/genproto v0.0.0-20240814211410-ddb44dafa142 h1:oLiyxGgE+rt22du google.golang.org/genproto v0.0.0-20240814211410-ddb44dafa142/go.mod h1:G11eXq53iI5Q+kyNOmCvnzBaxEA2Q/Ik5Tj7nqBE8j4= google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 h1:wKguEg1hsxI2/L3hUYrpo1RVi48K+uTyzKqprwLXsb8= google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142/go.mod h1:d6be+8HhtEtucleCbxpPW9PA9XwISACu8nvpPqF0BVo= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:pPJltXNxVzT4pK9yD8vR9X75DaWYYmLGMsEvBfFQZzQ= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f h1:cUMEy+8oS78BWIH9OWazBkzbr090Od9tWBNtZHkOhf0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -1362,8 +1364,8 @@ google.golang.org/grpc v1.48.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACu google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= google.golang.org/grpc v1.50.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= -google.golang.org/grpc v1.66.2 h1:3QdXkuq3Bkh7w+ywLdLvM56cmGvQHUMZpiCzt6Rqaoo= -google.golang.org/grpc v1.66.2/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y= +google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E= +google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= 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= diff --git a/x/upgrade/keeper/abci.go b/x/upgrade/keeper/abci.go index afaad8cf849b..efb06bf3ccbc 100644 --- a/x/upgrade/keeper/abci.go +++ b/x/upgrade/keeper/abci.go @@ -19,7 +19,8 @@ import ( // a migration to be executed if needed upon this switch (migration defined in the new binary) // skipUpgradeHeightArray is a set of block heights for which the upgrade must be skipped func (k Keeper) PreBlocker(ctx context.Context) error { - defer telemetry.ModuleMeasureSince(types.ModuleName, telemetry.Now(), telemetry.MetricKeyBeginBlocker) + start := telemetry.Now() + defer telemetry.ModuleMeasureSince(types.ModuleName, start, telemetry.MetricKeyBeginBlocker) blockHeight := k.HeaderService.HeaderInfo(ctx).Height plan, err := k.GetUpgradePlan(ctx) diff --git a/x/upgrade/keeper/grpc_query_test.go b/x/upgrade/keeper/grpc_query_test.go index 2f799677273f..df97a2e72249 100644 --- a/x/upgrade/keeper/grpc_query_test.go +++ b/x/upgrade/keeper/grpc_query_test.go @@ -204,8 +204,6 @@ func (suite *UpgradeTestSuite) TestModuleVersions() { suite.Require().NoError(err) for _, tc := range testCases { - tc := tc - suite.Run(fmt.Sprintf("Case %s", tc.msg), func() { suite.SetupTest() // reset diff --git a/x/upgrade/keeper/keeper_test.go b/x/upgrade/keeper/keeper_test.go index 16b88d418a75..66297a3fe6d9 100644 --- a/x/upgrade/keeper/keeper_test.go +++ b/x/upgrade/keeper/keeper_test.go @@ -189,8 +189,6 @@ func (s *KeeperTestSuite) TestScheduleUpgrade() { } for _, tc := range cases { - tc := tc - s.Run(tc.name, func() { // reset suite s.SetupTest() diff --git a/x/upgrade/plan/downloader_test.go b/x/upgrade/plan/downloader_test.go index 60706b4ac6d1..863c231eea85 100644 --- a/x/upgrade/plan/downloader_test.go +++ b/x/upgrade/plan/downloader_test.go @@ -96,7 +96,7 @@ func (z TestZip) SaveAs(path string) error { return zipper.Close() } -// saveTestZip saves a TestZip in this test's Home/src directory with the given name. +// saveSrcTestZip saves a TestZip in this test's Home/src directory with the given name. // The full path to the saved archive is returned. func (s *DownloaderTestSuite) saveSrcTestZip(name string, z TestZip) string { fullName := filepath.Join(s.Home, "src", name) diff --git a/x/upgrade/plan/info_test.go b/x/upgrade/plan/info_test.go index 047cd49defa6..62c56c8f0cac 100644 --- a/x/upgrade/plan/info_test.go +++ b/x/upgrade/plan/info_test.go @@ -24,7 +24,7 @@ func TestInfoTestSuite(t *testing.T) { suite.Run(t, new(InfoTestSuite)) } -// saveSrcTestFile saves a TestFile in this test's Home/src directory. +// saveTestFile saves a TestFile in this test's Home/src directory. // The full path to the saved file is returned. func (s *InfoTestSuite) saveTestFile(f *TestFile) string { fullName, err := f.SaveIn(s.Home) diff --git a/x/upgrade/types/plan_test.go b/x/upgrade/types/plan_test.go index 423f12b1d47f..668528cfa69d 100644 --- a/x/upgrade/types/plan_test.go +++ b/x/upgrade/types/plan_test.go @@ -42,7 +42,6 @@ func TestPlanString(t *testing.T) { } for name, tc := range cases { - tc := tc // copy to local variable for scopelint t.Run(name, func(t *testing.T) { s := tc.p.String() require.Equal(t, tc.expect, s) @@ -93,7 +92,6 @@ func TestPlanValid(t *testing.T) { } for name, tc := range cases { - tc := tc // copy to local variable for scopelint t.Run(name, func(t *testing.T) { err := tc.p.ValidateBasic() if tc.valid { @@ -142,7 +140,6 @@ func TestShouldExecute(t *testing.T) { } for name, tc := range cases { - tc := tc // copy to local variable for scopelint t.Run(name, func(t *testing.T) { should := tc.p.ShouldExecute(tc.ctxHeight) assert.Equal(t, tc.expected, should) diff --git a/x/upgrade/types/storeloader_test.go b/x/upgrade/types/storeloader_test.go index d14d160f01ed..45e0b81df9fc 100644 --- a/x/upgrade/types/storeloader_test.go +++ b/x/upgrade/types/storeloader_test.go @@ -93,7 +93,6 @@ func TestSetLoader(t *testing.T) { v := []byte("value") for name, tc := range cases { - tc := tc t.Run(name, func(t *testing.T) { // prepare a db with some data db := coretesting.NewMemDB() diff --git a/x/validate/README.md b/x/validate/README.md new file mode 100644 index 000000000000..f077102a06ef --- /dev/null +++ b/x/validate/README.md @@ -0,0 +1,35 @@ +# x/validate + +:::tip +This module is only required when using runtime and runtime v2 and you want to make use of the pre-defined ante/poste handlers or tx validators. +::: + +The `x/validate` is an app module solely there to setup ante/post handlers on a runtime app (via baseapp options) and the global tx validators on a runtime/v2 app (via app module). Depinject will automatically inject the ante/post handlers and tx validators into the app. Module specific tx validators should be registered on their own modules. + +## Extra TxValidators + +It is possible to add extra tx validators to the app. This is useful when you want to add extra tx validators that do not belong to one specific module. For example, you can add a tx validator that checks if the tx is signed by a specific address. + +In your `app.go`, when using runtime/v2, supply the extra tx validators using `depinject`: + +```go +appConfig = depinject.Configs( + AppConfig(), + depinject.Supply( + []appmodulev2.TxValidator[transaction.Tx]{ + // Add extra tx validators here + } + ), +) +``` + +## Storage + +This module has no store key. Do not forget to add the module name in the `SkipStoreKeys` runtime config present in the app config. + +```go +SkipStoreKeys: []string{ + authtxconfig.DepinjectModuleName, + validate.ModuleName, +}, +``` diff --git a/x/validate/depinject.go b/x/validate/depinject.go new file mode 100644 index 000000000000..9f508717f04f --- /dev/null +++ b/x/validate/depinject.go @@ -0,0 +1,145 @@ +package validate + +import ( + "fmt" + + modulev1 "cosmossdk.io/api/cosmos/validate/module/v1" + appmodulev2 "cosmossdk.io/core/appmodule/v2" + "cosmossdk.io/core/server" + "cosmossdk.io/core/transaction" + "cosmossdk.io/depinject" + "cosmossdk.io/depinject/appconfig" + + "github.com/cosmos/cosmos-sdk/baseapp" + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/runtime" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/auth/ante" + "github.com/cosmos/cosmos-sdk/x/auth/ante/unorderedtx" + "github.com/cosmos/cosmos-sdk/x/auth/posthandler" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" +) + +// flagMinGasPricesV2 is the flag name for the minimum gas prices in the main server v2 component. +const flagMinGasPricesV2 = "server.minimum-gas-prices" + +func init() { + appconfig.RegisterModule(&modulev1.Module{}, + appconfig.Provide(ProvideModule), + ) +} + +type ModuleInputs struct { + depinject.In + + ModuleConfig *modulev1.Module + Environment appmodulev2.Environment + TxConfig client.TxConfig + DynamicConfig server.DynamicConfig `optional:"true"` + + AccountKeeper ante.AccountKeeper + BankKeeper authtypes.BankKeeper + ConsensusKeeper ante.ConsensusKeeper + FeeGrantKeeper ante.FeegrantKeeper `optional:"true"` + AccountAbstractionKeeper ante.AccountAbstractionKeeper `optional:"true"` + ExtraTxValidators []appmodulev2.TxValidator[transaction.Tx] `optional:"true"` + UnorderedTxManager *unorderedtx.Manager `optional:"true"` + TxFeeChecker ante.TxFeeChecker `optional:"true"` +} + +type ModuleOutputs struct { + depinject.Out + + Module appmodulev2.AppModule // Only useful for chains using server/v2. It setup tx validators that don't belong to other modules. + BaseAppOption runtime.BaseAppOption // Only useful for chains using baseapp. Server/v2 chains use TxValidator. +} + +func ProvideModule(in ModuleInputs) ModuleOutputs { + svd := ante.NewSigVerificationDecorator( + in.AccountKeeper, + in.TxConfig.SignModeHandler(), + ante.DefaultSigVerificationGasConsumer, + in.AccountAbstractionKeeper, // can be nil + ) + + var ( + err error + minGasPrices sdk.DecCoins + feeTxValidator *ante.DeductFeeDecorator + unorderedTxValidator *ante.UnorderedTxDecorator + ) + + if in.DynamicConfig != nil { + minGasPricesStr := in.DynamicConfig.GetString(flagMinGasPricesV2) + minGasPrices, err = sdk.ParseDecCoins(minGasPricesStr) + if err != nil { + panic(fmt.Sprintf("invalid minimum gas prices: %v", err)) + } + + feeTxValidator = ante.NewDeductFeeDecorator(in.AccountKeeper, in.BankKeeper, in.FeeGrantKeeper, in.TxFeeChecker) + feeTxValidator.SetMinGasPrices(minGasPrices) // set min gas price in deduct fee decorator + } + + if in.UnorderedTxManager != nil { + unorderedTxValidator = ante.NewUnorderedTxDecorator(unorderedtx.DefaultMaxTimeoutDuration, in.UnorderedTxManager, in.Environment, ante.DefaultSha256Cost) + } + + return ModuleOutputs{ + Module: NewAppModule(svd, feeTxValidator, unorderedTxValidator, in.ExtraTxValidators...), + BaseAppOption: newBaseAppOption(in), + } +} + +// newBaseAppOption returns baseapp option that sets the ante handler and post handler +// and set the tx encoder and decoder on baseapp. +func newBaseAppOption(in ModuleInputs) func(app *baseapp.BaseApp) { + return func(app *baseapp.BaseApp) { + anteHandler, err := newAnteHandler(in) + if err != nil { + panic(err) + } + app.SetAnteHandler(anteHandler) + + // PostHandlers + // In v0.46, the SDK introduces _postHandlers_. PostHandlers are like + // antehandlers, but are run _after_ the `runMsgs` execution. They are also + // defined as a chain, and have the same signature as antehandlers. + // + // In baseapp, postHandlers are run in the same store branch as `runMsgs`, + // meaning that both `runMsgs` and `postHandler` state will be committed if + // both are successful, and both will be reverted if any of the two fails. + // + // The SDK exposes a default empty postHandlers chain. + // + // Please note that changing any of the anteHandler or postHandler chain is + // likely to be a state-machine breaking change, which needs a coordinated + // upgrade. + postHandler, err := posthandler.NewPostHandler( + posthandler.HandlerOptions{}, + ) + if err != nil { + panic(err) + } + app.SetPostHandler(postHandler) + } +} + +func newAnteHandler(in ModuleInputs) (sdk.AnteHandler, error) { + anteHandler, err := ante.NewAnteHandler( + ante.HandlerOptions{ + Environment: in.Environment, + AccountKeeper: in.AccountKeeper, + ConsensusKeeper: in.ConsensusKeeper, + BankKeeper: in.BankKeeper, + SignModeHandler: in.TxConfig.SignModeHandler(), + FeegrantKeeper: in.FeeGrantKeeper, + SigGasConsumer: ante.DefaultSigVerificationGasConsumer, + UnorderedTxManager: in.UnorderedTxManager, + }, + ) + if err != nil { + return nil, fmt.Errorf("failed to create ante handler: %w", err) + } + + return anteHandler, nil +} diff --git a/x/validate/keys.go b/x/validate/keys.go new file mode 100644 index 000000000000..de6282ccd9de --- /dev/null +++ b/x/validate/keys.go @@ -0,0 +1,4 @@ +package validate + +// ModuleName is the name of the validate module. +const ModuleName = "validate" diff --git a/x/auth/tx/config/module.go b/x/validate/module.go similarity index 99% rename from x/auth/tx/config/module.go rename to x/validate/module.go index 2529f36bc8e3..f547e63fe085 100644 --- a/x/auth/tx/config/module.go +++ b/x/validate/module.go @@ -1,4 +1,4 @@ -package tx +package validate import ( "context"