Merge branch 'master' into spoorthi/9706-refactor-validate-balance

This commit is contained in:
Spoorthi Satheesha 2021-08-04 15:00:12 +02:00 committed by GitHub
commit 0c7c6cf998
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
33 changed files with 1035 additions and 130 deletions

View File

@ -15,7 +15,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: technote-space/get-diff-action@v4
- uses: technote-space/get-diff-action@v5
id: git_diff
with:
PATTERNS: |
@ -30,7 +30,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: technote-space/get-diff-action@v4
- uses: technote-space/get-diff-action@v5
id: git_diff
with:
PATTERNS: |
@ -45,7 +45,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: technote-space/get-diff-action@v4
- uses: technote-space/get-diff-action@v5
id: git_diff
with:
PATTERNS: |

View File

@ -10,7 +10,7 @@ jobs:
runs-on: ubuntu-latest
timeout-minutes: 3
steps:
- uses: styfle/cancel-workflow-action@0.9.0
- uses: styfle/cancel-workflow-action@0.9.1
with:
workflow_id: 872925,1013614,1134055
access_token: ${{ github.token }}

View File

@ -14,7 +14,7 @@ jobs:
timeout-minutes: 6
steps:
- uses: actions/checkout@v2
- uses: technote-space/get-diff-action@v4
- uses: technote-space/get-diff-action@v5
with:
PATTERNS: |
**/**.go

View File

@ -10,7 +10,7 @@ jobs:
timeout-minutes: 5
steps:
- uses: actions/checkout@master
- uses: technote-space/get-diff-action@v4
- uses: technote-space/get-diff-action@v5
with:
PATTERNS: |
**/**.proto
@ -21,7 +21,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@master
- uses: technote-space/get-diff-action@v4
- uses: technote-space/get-diff-action@v5
with:
PATTERNS: |
**/**.proto

View File

@ -46,7 +46,7 @@ jobs:
go-version: 1.16
- name: Display go version
run: go version
- uses: technote-space/get-diff-action@v4
- uses: technote-space/get-diff-action@v5
with:
PATTERNS: |
**/**.go
@ -72,7 +72,7 @@ jobs:
go-version: 1.16
- name: Display go version
run: go version
- uses: technote-space/get-diff-action@v4
- uses: technote-space/get-diff-action@v5
with:
SUFFIX_FILTER: |
**/**.go
@ -100,7 +100,7 @@ jobs:
go-version: 1.16
- name: Display go version
run: go version
- uses: technote-space/get-diff-action@v4
- uses: technote-space/get-diff-action@v5
with:
SUFFIX_FILTER: |
**/**.go
@ -128,7 +128,7 @@ jobs:
go-version: 1.16
- name: Display go version
run: go version
- uses: technote-space/get-diff-action@v4
- uses: technote-space/get-diff-action@v5
with:
SUFFIX_FILTER: |
**/**.go

View File

@ -33,7 +33,7 @@ jobs:
- uses: actions/setup-go@v2.1.3
with:
go-version: 1.16
- uses: technote-space/get-diff-action@v4
- uses: technote-space/get-diff-action@v5
id: git_diff
with:
PATTERNS: |
@ -52,7 +52,7 @@ jobs:
go-version: 1.16
- name: Display go version
run: go version
- uses: technote-space/get-diff-action@v4
- uses: technote-space/get-diff-action@v5
id: git_diff
with:
PREFIX_FILTER: |
@ -103,7 +103,7 @@ jobs:
- uses: actions/setup-go@v2.1.3
with:
go-version: 1.16
- uses: technote-space/get-diff-action@v4
- uses: technote-space/get-diff-action@v5
with:
PATTERNS: |
**/**.go
@ -127,7 +127,7 @@ jobs:
needs: tests
steps:
- uses: actions/checkout@v2
- uses: technote-space/get-diff-action@v4
- uses: technote-space/get-diff-action@v5
with:
PATTERNS: |
**/**.go
@ -181,7 +181,7 @@ jobs:
- uses: actions/setup-go@v2.1.3
with:
go-version: 1.16
- uses: technote-space/get-diff-action@v4
- uses: technote-space/get-diff-action@v5
with:
PATTERNS: |
**/**.go
@ -205,7 +205,7 @@ jobs:
timeout-minutes: 10
steps:
- uses: actions/checkout@v2
- uses: technote-space/get-diff-action@v4
- uses: technote-space/get-diff-action@v5
id: git_diff
with:
PATTERNS: |
@ -225,7 +225,7 @@ jobs:
- uses: actions/setup-go@v2.1.3
with:
go-version: 1.16
- uses: technote-space/get-diff-action@v4
- uses: technote-space/get-diff-action@v5
id: git_diff
with:
PATTERNS: |

View File

@ -54,7 +54,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
* (client/keys) [\#9407](https://github.com/cosmos/cosmos-sdk/pull/9601) Added `keys rename` CLI command and `Keyring.Rename` interface method to rename a key in the keyring.
* (x/slashing) [\#9458](https://github.com/cosmos/cosmos-sdk/pull/9458) Coins burned from slashing is now returned from Slash function and included in Slash event.
* [\#9246](https://github.com/cosmos/cosmos-sdk/pull/9246) The `New` method for the network package now returns an error.
* [\#9519](https://github.com/cosmos/cosmos-sdk/pull/9519) `DeleteDeposits` renamed to `DeleteAndBurnDeposits`, `RefundDeposits` renamed to `RefundAndDeleteDeposits`
* [\#9519](https://github.com/cosmos/cosmos-sdk/pull/9519) `DeleteDeposits` renamed to `DeleteAndBurnDeposits`, `RefundDeposits` renamed to `RefundAndDeleteDeposits`
* (codec) [\#9521](https://github.com/cosmos/cosmos-sdk/pull/9521) Removed deprecated `clientCtx.JSONCodec` from `client.Context`.
* (codec) [\#9521](https://github.com/cosmos/cosmos-sdk/pull/9521) Rename `EncodingConfig.Marshaler` to `Codec`.
* [\#9418](https://github.com/cosmos/cosmos-sdk/pull/9418) `sdk.Msg`'s `GetSigners()` method updated to return `[]string`.
@ -63,15 +63,17 @@ Ref: https://keepachangelog.com/en/1.0.0/
* [\#9432](https://github.com/cosmos/cosmos-sdk/pull/9432) `ConsensusParamsKeyTable` moved from `params/keeper` to `params/types`
* [\#9576](https://github.com/cosmos/cosmos-sdk/pull/9576) Add debug error message to `sdkerrors.QueryResult` when enabled
* [\#9650](https://github.com/cosmos/cosmos-sdk/pull/9650) Removed deprecated message handler implementation from the SDK modules.
* (x/capability) [\#9836](https://github.com/cosmos/cosmos-sdk/pull/9836) Removed `InitializeAndSeal(ctx sdk.Context)` and replaced with `Seal()`. App must add x/capability to begin blockers which will assure that the x/capability keeper is properly initialized. The x/capability begin blocker must be run before any other module which uses x/capability.
### Client Breaking Changes
* [\#9594](https://github.com/cosmos/cosmos-sdk/pull/9594) Remove legacy REST API. Please see the [REST Endpoints Migration guide](https://docs.cosmos.network/master/migrations/rest.html) to migrate to the new REST endpoints.
* [\#9781](https://github.com/cosmos/cosmos-sdk/pull/9781) Improve`withdraw-all-rewards` UX when broadcast mode `async` or `async` is used.
* [\#9785](https://github.com/cosmos/cosmos-sdk/issues/9785) Missing coin denomination in logs
### CLI Breaking Changes
* [\#9827](https://github.com/cosmos/cosmos-sdk/pull/9827) Ensure input parity of validator public key input between `tx staking create-validator` and `gentx`.
* [\#9246](https://github.com/cosmos/cosmos-sdk/pull/9246) Removed the CLI flag `--setup-config-only` from the `testnet` command and added the subcommand `init-files`.
* [\#9371](https://github.com/cosmos/cosmos-sdk/pull/9371) Non-zero default fees/Server will error if there's an empty value for min-gas-price in app.toml
@ -93,7 +95,9 @@ Ref: https://keepachangelog.com/en/1.0.0/
* (server) [#9704](https://github.com/cosmos/cosmos-sdk/pull/9704) Start GRPCWebServer in goroutine, avoid blocking other services from starting.
* [\#9762](https://github.com/cosmos/cosmos-sdk/pull/9762) The init command uses the chain-id from the client config if --chain-id is not provided
* [\#9793](https://github.com/cosmos/cosmos-sdk/pull/9793) Fixed ECDSA/secp256r1 transaction malleability.
* [\#9829](https://github.com/cosmos/cosmos-sdk/pull/9829) Fixed Coin denom sorting not being checked during `Balance.Validate` check. Refactored the Validation logic to use `Coins.Validate` for `Balance.Coins`
* [\#9836](https://github.com/cosmos/cosmos-sdk/pull/9836) Fixes capability initialization issue on tx revert by moving initialization logic to `InitChain` and `BeginBlock`.
* [\#9829](https://github.com/cosmos/cosmos-sdk/pull/9829) Fixed Coin denom sorting not being checked during `Balance.Validate` check. Refactored the Validation logic to use `Coins.Validate` for `Balance.Coins`.
### State Machine Breaking

View File

@ -12,7 +12,7 @@
# TODO: demo connecting rest-server (or is this in server now?)
FROM golang:alpine AS build-env
# Install minimum necessary dependencies,
# Install minimum necessary dependencies
ENV PACKAGES curl make git libc-dev bash gcc linux-headers eudev-dev python3
RUN apk add --no-cache $PACKAGES

View File

@ -77,3 +77,7 @@ When writing ADRs, follow the same best practices for writing RFCs. When writing
- [ADR 038: State Listening](./adr-038-state-listening.md)
- [ADR 039: Epoched Staking](./adr-039-epoched-staking.md)
- [ADR 040: Storage and SMT State Commitments](./adr-040-storage-and-smt-state-commitments.md)
### Draft
- [ADR 044: Guidelines for Updating Protobuf Definitions](./adr-044-protobuf-updates-guidelines.md)

View File

@ -0,0 +1,109 @@
# ADR 044: Guidelines for Updating Protobuf Definitions
## Changelog
- 28.06.2021: Initial Draft
## Status
Draft
## Abstract
This ADR provides guidelines and recommended practices when updating Protobuf definitions. These guidelines are targeting module developers.
## Context
The SDK maintains a set of [Protobuf definitions](https://github.com/cosmos/cosmos-sdk/tree/master/proto/cosmos). It is important to correctly design Protobuf definitions to avoid any breaking changes within the same version. The reasons are to not break tooling (including indexers and explorers), wallets and other third-party integrations.
When making changes to these Protobuf definitions, the SDK currently only follows [Buf's](https://docs.buf.build/) recommendations. We noticed however that Buf's recommendations might still result in breaking changes in the SDK in some cases. For example:
- Adding fields to `Msg`s. Adding fields is a not a Protobuf spec-breaking operation. However, when adding new fields to `Msg`s, the unknown field rejection will throw an error when sending the new `Msg` to an older node.
- Marking fields as `reserved`. Protobuf proposes the `reserved` keyword for removing fields without the need to bump the package version. However, by doing so, client backwards compatibility is broken as Protobuf doesn't generate anything for `reserved` fields. See [#9446](https://github.com/cosmos/cosmos-sdk/issues/9446) for more details on this issue.
Moreover, module developers often face other questions around Protobuf definitions such as "Can I rename a field?" or "Can I deprecate a field?" This ADR aims to answer all these questions by providing clear guidelines about allowed updates for Protobuf definitions.
## Decision
We decide to keep [Buf's](https://docs.buf.build/) recommendations with the following exceptions:
- `UNARY_RPC`: the SDK currently does not support streaming RPCs.
- `COMMENT_FIELD`: the SDK allows fields with no comments.
- `SERVICE_SUFFIX`: we use the `Query` and `Msg` service naming convention, which doesn't use the `-Service` suffix.
- `PACKAGE_VERSION_SUFFIX`: some packages, such as `cosmos.crypto.ed25519`, don't use a version suffix.
- `RPC_REQUEST_STANDARD_NAME`: Requests for the `Msg` service don't have the `-Request` suffix to keep backwards compatibility.
On top of Buf's recommendations we add the following guidelines that are specific to the SDK.
### Updating Protobuf Definition Without Bumping Version
#### 1. `Msg`s MUST NOT have new fields.
When processing `Msg`s, the SDK's antehandlers are strict and don't allow unknown fields in `Msg`s. This is checked by the unknown field rejection in the [`codec/unknownproto` package](https://github.com/cosmos/cosmos-sdk/blob/master/codec/unknownproto).
Now imagine a v0.43 node accepting a `MsgExample` transaction, and in v0.44 the chain developer decides to add a field to `MsgExample`. A client developer, which only manipulates Protobuf definitions, would see that `MsgExample` has a new field, and will populate it. However, sending the new `MsgExample` to an old v0.43 node would cause the v0.43 node to reject the `MsgExample` because of the unknown field. The expectation that the same Protobuf version can be used across multiple node versions MUST be guaranteed.
For this reason, module developers MUST NOT add new fields to existing `Msg`s.
It is worth mentioning that this does not limit adding fields to a `Msg`, but also to all nested structs and `Any`s inside a `Msg`.
#### 2. Non-`Msg`-related Protobuf definitions MAY have new fields.
On the other hand, module developers MAY add new fields to Protobuf definitions related to the `Query` service or to objects which are saved in the store. This recommendation follows the Protobuf specification, but is added in this document for clarity.
#### 3. Fields MAY be marked as `deprecated`, and nodes MAY implement a protocol-breaking change for handling these fields.
Protobuf supports the [`deprecated` field option](https://developers.google.com/protocol-buffers/docs/proto#options), and this option MAY be used on any field, including `Msg` fields. If a node handles a Protobuf message with a non-empty deprecated field, the node MAY change its behavior upon processing it, even in a protocol-breaking way. When possible, the node MUST handle backwards compatibility without breaking the consensus (unless we increment the proto version).
As an example, the SDK v0.42 to v0.43 update contained two Protobuf-breaking changes, listed below. Instead of bumping the package versions from `v1beta1` to `v1`, the SDK team decided to follow this guideline, by reverting the breaking changes, marking those changes as deprecated, and modifying the node implementation when processing messages with deprecated fields. More specifically:
- The SDK recently removed support for [time-based software upgrades](https://github.com/cosmos/cosmos-sdk/pull/8849). As such, the `time` field has been marked as deprecated in `cosmos.upgrade.v1beta1.Plan`. Moreover, the node will reject any proposal containing an upgrade Plan whose `time` field is non-empty.
- The SDK now supports [governance split votes](./adr-037-gov-split-vote.md). When querying for votes, the returned `cosmos.gov.v1beta1.Vote` message has its `option` field (used for 1 vote option) deprecated in favor of its `options` field (allowing multiple vote options). Whenever possible, the SDK still populates the deprecated `option` field, that is, if and only if the `len(options) == 1` and `options[0].Weight == 1.0`.
#### 4. Fields MUST NOT be renamed.
Whereas the official Protobuf recommendations do not prohibit renaming fields, as it does not break the Protobuf binary representation, the SDK explicitly forbids renaming fields in Protobuf structs. The main reason for this choice is to avoid introducing breaking changes for clients, which often rely on hard-coded fields from generated types. Moreover, renaming fields will lead to client-breaking JSON representations of Protobuf definitions, used in REST endpoints and in the CLI.
### Incrementing Protobuf Package Version
TODO, needs architecture review. Some topics:
- Bumping versions frequency
- When bumping versions, should the SDK support both versions?
- i.e. v1beta1 -> v1, should we have two folders in the SDK, and handlers for both versions?
- mention ADR-023 Protobuf naming
## Consequences
> This section describes the resulting context, after applying the decision. All consequences should be listed here, not just the "positive" ones. A particular decision may have positive, negative, and neutral consequences, but all of them affect the team and project in the future.
### Backwards Compatibility
> All ADRs that introduce backwards incompatibilities must include a section describing these incompatibilities and their severity. The ADR must explain how the author proposes to deal with these incompatibilities. ADR submissions without a sufficient backwards compatibility treatise may be rejected outright.
### Positive
- less pain to tool developers
- more compatibility in the ecosystem
- ...
### Negative
{negative consequences}
### Neutral
- more rigor in Protobuf review
## Further Discussions
This ADR is still in the DRAFT stage, and the "Incrementing Protobuf Package Version" will be filled in once we make a decision on how to correctly do it.
## Test Cases [optional]
Test cases for an implementation are mandatory for ADRs that are affecting consensus changes. Other ADRs can choose to include links to test cases if applicable.
## References
- [#9445](https://github.com/cosmos/cosmos-sdk/issues/9445) Release proto definitions v1
- [#9446](https://github.com/cosmos/cosmos-sdk/issues/9446) Address v1beta1 proto breaking changes

View File

@ -162,7 +162,7 @@ Each module should also implement the `RegisterServices` method as part of the [
### gRPC `Query` Services
gRPC `Query` services are introduced in the v0.40 Stargate release. They allow users to query the state using [gRPC](https://grpc.io). They are enabled by default, and can be configued under the `grpc.enable` and `grpc.address` fields inside [`app.toml`](../run-node/run-node.md#configuring-the-node-using-apptoml).
gRPC `Query` services are introduced in the v0.40 Stargate release. They allow users to query the state using [gRPC](https://grpc.io). They are enabled by default, and can be configured under the `grpc.enable` and `grpc.address` fields inside [`app.toml`](../run-node/run-node.md#configuring-the-node-using-apptoml).
gRPC `Query` services are defined in the module's Protobuf definition files, specifically inside `query.proto`. The `query.proto` definition file exposes a single `Query` [Protobuf service](https://developers.google.com/protocol-buffers/docs/proto#services). Each gRPC query endpoint corresponds to a service method, starting with the `rpc` keyword, inside the `Query` service.

View File

@ -21,6 +21,8 @@
- [QueryAccountResponse](#cosmos.auth.v1beta1.QueryAccountResponse)
- [QueryAccountsRequest](#cosmos.auth.v1beta1.QueryAccountsRequest)
- [QueryAccountsResponse](#cosmos.auth.v1beta1.QueryAccountsResponse)
- [QueryModuleAccountsRequest](#cosmos.auth.v1beta1.QueryModuleAccountsRequest)
- [QueryModuleAccountsResponse](#cosmos.auth.v1beta1.QueryModuleAccountsResponse)
- [QueryParamsRequest](#cosmos.auth.v1beta1.QueryParamsRequest)
- [QueryParamsResponse](#cosmos.auth.v1beta1.QueryParamsResponse)
@ -898,6 +900,31 @@ QueryAccountsResponse is the response type for the Query/Accounts RPC method.
<a name="cosmos.auth.v1beta1.QueryModuleAccountsRequest"></a>
### QueryModuleAccountsRequest
QueryModuleAccountsRequest is the request type for the Query/ModuleAccounts RPC method.
<a name="cosmos.auth.v1beta1.QueryModuleAccountsResponse"></a>
### QueryModuleAccountsResponse
QueryModuleAccountsResponse is the response type for the Query/ModuleAccounts RPC method.
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `accounts` | [google.protobuf.Any](#google.protobuf.Any) | repeated | |
<a name="cosmos.auth.v1beta1.QueryParamsRequest"></a>
### QueryParamsRequest
@ -939,6 +966,7 @@ Query defines the gRPC querier service.
| `Accounts` | [QueryAccountsRequest](#cosmos.auth.v1beta1.QueryAccountsRequest) | [QueryAccountsResponse](#cosmos.auth.v1beta1.QueryAccountsResponse) | Accounts returns all the existing accounts | GET|/cosmos/auth/v1beta1/accounts|
| `Account` | [QueryAccountRequest](#cosmos.auth.v1beta1.QueryAccountRequest) | [QueryAccountResponse](#cosmos.auth.v1beta1.QueryAccountResponse) | Account returns account details based on address. | GET|/cosmos/auth/v1beta1/accounts/{address}|
| `Params` | [QueryParamsRequest](#cosmos.auth.v1beta1.QueryParamsRequest) | [QueryParamsResponse](#cosmos.auth.v1beta1.QueryParamsResponse) | Params queries all parameters. | GET|/cosmos/auth/v1beta1/params|
| `ModuleAccounts` | [QueryModuleAccountsRequest](#cosmos.auth.v1beta1.QueryModuleAccountsRequest) | [QueryModuleAccountsResponse](#cosmos.auth.v1beta1.QueryModuleAccountsResponse) | ModuleAccounts returns all the existing Module Accounts. | GET|/cosmos/auth/v1beta1/module_accounts|
<!-- end services -->

View File

@ -12,7 +12,7 @@ Upgrade your app modules smoothly with custom in-place store migration logic. {s
The Cosmos SDK uses two methods to perform upgrades.
- Exporting the entire application state to a JSON file using the `export` CLI command, making changes, and then starting a new binary with the changed JSON file as the genesis file. See [Chain Upgrade Guide to v0.42](../v0.42/migrations/chain-upgrade-guide-040.html).
- Exporting the entire application state to a JSON file using the `export` CLI command, making changes, and then starting a new binary with the changed JSON file as the genesis file. See [Chain Upgrade Guide to v0.42](https://docs.cosmos.network/v0.42/migrations/chain-upgrade-guide-040.html).
- Version v0.43 and later can perform upgrades in place to significantly decrease the upgrade time for chains with a larger state. Use the [Module Upgrade Guide](../building-modules/upgrade.md) to set up your application modules to take advantage of in-place upgrades.

View File

@ -26,6 +26,11 @@ service Query {
rpc Params(QueryParamsRequest) returns (QueryParamsResponse) {
option (google.api.http).get = "/cosmos/auth/v1beta1/params";
}
// ModuleAccounts returns all the existing module accounts.
rpc ModuleAccounts(QueryModuleAccountsRequest) returns (QueryModuleAccountsResponse) {
option (google.api.http).get = "/cosmos/auth/v1beta1/module_accounts";
}
}
// QueryAccountsRequest is the request type for the Query/Accounts RPC method.
@ -66,3 +71,11 @@ message QueryParamsResponse {
// params defines the parameters of the module.
Params params = 1 [(gogoproto.nullable) = false];
}
// QueryModuleAccountsRequest is the request type for the Query/ModuleAccounts RPC method.
message QueryModuleAccountsRequest {}
// QueryModuleAccountsResponse is the response type for the Query/ModuleAccounts RPC method.
message QueryModuleAccountsResponse {
repeated google.protobuf.Any accounts = 1 [(cosmos_proto.accepts_interface) = "ModuleAccountI"];
}

View File

@ -13,7 +13,6 @@ import (
abci "github.com/tendermint/tendermint/abci/types"
"github.com/tendermint/tendermint/libs/log"
tmos "github.com/tendermint/tendermint/libs/os"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
dbm "github.com/tendermint/tm-db"
"github.com/cosmos/cosmos-sdk/baseapp"
@ -208,7 +207,9 @@ func NewSimApp(
authzkeeper.StoreKey,
)
tkeys := sdk.NewTransientStoreKeys(paramstypes.TStoreKey)
memKeys := sdk.NewMemoryStoreKeys(capabilitytypes.MemStoreKey)
// NOTE: The testingkey is just mounted for testing purposes. Actual applications should
// not include this key.
memKeys := sdk.NewMemoryStoreKeys(capabilitytypes.MemStoreKey, "testingkey")
app := &SimApp{
BaseApp: bApp,
@ -227,6 +228,9 @@ func NewSimApp(
bApp.SetParamStore(app.ParamsKeeper.Subspace(baseapp.Paramspace).WithKeyTable(paramstypes.ConsensusParamsKeyTable()))
app.CapabilityKeeper = capabilitykeeper.NewKeeper(appCodec, keys[capabilitytypes.StoreKey], memKeys[capabilitytypes.MemStoreKey])
// Applications that wish to enforce statically created ScopedKeepers should call `Seal` after creating
// their scoped modules in `NewApp` with `ScopeToModule`
app.CapabilityKeeper.Seal()
// add keepers
app.AccountKeeper = authkeeper.NewAccountKeeper(
@ -322,8 +326,9 @@ func NewSimApp(
// there is nothing left over in the validator fee pool, so as to keep the
// CanWithdrawInvariant invariant.
// NOTE: staking module is required if HistoricalEntries param > 0
// NOTE: capability module's beginblocker must come before any modules using capabilities (e.g. IBC)
app.mm.SetOrderBeginBlockers(
upgradetypes.ModuleName, minttypes.ModuleName, distrtypes.ModuleName, slashingtypes.ModuleName,
upgradetypes.ModuleName, capabilitytypes.ModuleName, minttypes.ModuleName, distrtypes.ModuleName, slashingtypes.ModuleName,
evidencetypes.ModuleName, stakingtypes.ModuleName,
)
app.mm.SetOrderEndBlockers(crisistypes.ModuleName, govtypes.ModuleName, stakingtypes.ModuleName)
@ -399,16 +404,6 @@ func NewSimApp(
if err := app.LoadLatestVersion(); err != nil {
tmos.Exit(err.Error())
}
// Initialize and seal the capability keeper so all persistent capabilities
// are loaded in-memory and prevent any further modules from creating scoped
// sub-keepers.
// This must be done during creation of baseapp rather than in InitChain so
// that in-memory capabilities get regenerated on app restart.
// Note that since this reads from the store, we can only perform it when
// `loadLatest` is set to true.
ctx := app.BaseApp.NewUncachedContext(true, tmproto.Header{})
app.CapabilityKeeper.InitializeAndSeal(ctx)
}
return app

View File

@ -1,6 +1,7 @@
package cli
import (
"context"
"fmt"
"strings"
@ -42,6 +43,7 @@ func GetQueryCmd() *cobra.Command {
GetAccountCmd(),
GetAccountsCmd(),
QueryParamsCmd(),
QueryModuleAccountsCmd(),
)
return cmd
@ -142,6 +144,33 @@ func GetAccountsCmd() *cobra.Command {
return cmd
}
// QueryAllModuleAccountsCmd returns a list of all the existing module accounts with their account information and permissions
func QueryModuleAccountsCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "module-accounts",
Short: "Query all module accounts",
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientQueryContext(cmd)
if err != nil {
return err
}
queryClient := types.NewQueryClient(clientCtx)
res, err := queryClient.ModuleAccounts(context.Background(), &types.QueryModuleAccountsRequest{})
if err != nil {
return err
}
return clientCtx.PrintProto(res)
},
}
flags.AddQueryFlagsToCmd(cmd)
return cmd
}
// QueryTxsByEventsCmd returns a command to search through transactions by events.
func QueryTxsByEventsCmd() *cobra.Command {
cmd := &cobra.Command{

View File

@ -83,3 +83,28 @@ func (ak AccountKeeper) Params(c context.Context, req *types.QueryParamsRequest)
return &types.QueryParamsResponse{Params: params}, nil
}
// ModuleAccounts returns all the existing Module Accounts
func (ak AccountKeeper) ModuleAccounts(c context.Context, req *types.QueryModuleAccountsRequest) (*types.QueryModuleAccountsResponse, error) {
if req == nil {
return nil, status.Error(codes.InvalidArgument, "empty request")
}
ctx := sdk.UnwrapSDKContext(c)
modAccounts := make([]*codectypes.Any, 0, len(ak.permAddrs))
for moduleName := range ak.permAddrs {
account := ak.GetModuleAccount(ctx, moduleName)
if account == nil {
return nil, status.Errorf(codes.NotFound, "account %s not found", moduleName)
}
any, err := codectypes.NewAnyWithValue(account)
if err != nil {
return nil, status.Errorf(codes.Internal, err.Error())
}
modAccounts = append(modAccounts, any)
}
return &types.QueryModuleAccountsResponse{Accounts: modAccounts}, nil
}

View File

@ -191,3 +191,84 @@ func (suite *KeeperTestSuite) TestGRPCQueryParameters() {
})
}
}
func (suite *KeeperTestSuite) TestGRPCQueryModuleAccounts() {
var (
req *types.QueryModuleAccountsRequest
)
testCases := []struct {
msg string
malleate func()
expPass bool
posttests func(res *types.QueryModuleAccountsResponse)
}{
{
"success",
func() {
req = &types.QueryModuleAccountsRequest{}
},
true,
func(res *types.QueryModuleAccountsResponse) {
var mintModuleExists = false
for _, acc := range res.Accounts {
var account types.AccountI
err := suite.app.InterfaceRegistry().UnpackAny(acc, &account)
suite.Require().NoError(err)
moduleAccount, ok := account.(types.ModuleAccountI)
suite.Require().True(ok)
if moduleAccount.GetName() == "mint" {
mintModuleExists = true
}
}
suite.Require().True(mintModuleExists)
},
},
{
"invalid module name",
func() {
req = &types.QueryModuleAccountsRequest{}
},
true,
func(res *types.QueryModuleAccountsResponse) {
var mintModuleExists = false
for _, acc := range res.Accounts {
var account types.AccountI
err := suite.app.InterfaceRegistry().UnpackAny(acc, &account)
suite.Require().NoError(err)
moduleAccount, ok := account.(types.ModuleAccountI)
suite.Require().True(ok)
if moduleAccount.GetName() == "falseCase" {
mintModuleExists = true
}
}
suite.Require().False(mintModuleExists)
},
},
}
for _, tc := range testCases {
suite.Run(fmt.Sprintf("Case %s", tc.msg), func() {
suite.SetupTest() // reset
tc.malleate()
ctx := sdk.WrapSDKContext(suite.ctx)
res, err := suite.queryClient.ModuleAccounts(ctx, req)
if tc.expPass {
suite.Require().NoError(err)
suite.Require().NotNil(res)
} else {
suite.Require().Error(err)
suite.Require().Nil(res)
}
tc.posttests(res)
})
}
}

View File

@ -301,6 +301,88 @@ func (m *QueryParamsResponse) GetParams() Params {
return Params{}
}
// QueryModuleAccountsRequest is the request type for the Query/ModuleAccounts RPC method.
type QueryModuleAccountsRequest struct {
}
func (m *QueryModuleAccountsRequest) Reset() { *m = QueryModuleAccountsRequest{} }
func (m *QueryModuleAccountsRequest) String() string { return proto.CompactTextString(m) }
func (*QueryModuleAccountsRequest) ProtoMessage() {}
func (*QueryModuleAccountsRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_c451370b3929a27c, []int{6}
}
func (m *QueryModuleAccountsRequest) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *QueryModuleAccountsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
if deterministic {
return xxx_messageInfo_QueryModuleAccountsRequest.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 *QueryModuleAccountsRequest) XXX_Merge(src proto.Message) {
xxx_messageInfo_QueryModuleAccountsRequest.Merge(m, src)
}
func (m *QueryModuleAccountsRequest) XXX_Size() int {
return m.Size()
}
func (m *QueryModuleAccountsRequest) XXX_DiscardUnknown() {
xxx_messageInfo_QueryModuleAccountsRequest.DiscardUnknown(m)
}
var xxx_messageInfo_QueryModuleAccountsRequest proto.InternalMessageInfo
// QueryModuleAccountsResponse is the response type for the Query/ModuleAccounts RPC method.
type QueryModuleAccountsResponse struct {
Accounts []*types.Any `protobuf:"bytes,1,rep,name=accounts,proto3" json:"accounts,omitempty"`
}
func (m *QueryModuleAccountsResponse) Reset() { *m = QueryModuleAccountsResponse{} }
func (m *QueryModuleAccountsResponse) String() string { return proto.CompactTextString(m) }
func (*QueryModuleAccountsResponse) ProtoMessage() {}
func (*QueryModuleAccountsResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_c451370b3929a27c, []int{7}
}
func (m *QueryModuleAccountsResponse) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *QueryModuleAccountsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
if deterministic {
return xxx_messageInfo_QueryModuleAccountsResponse.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 *QueryModuleAccountsResponse) XXX_Merge(src proto.Message) {
xxx_messageInfo_QueryModuleAccountsResponse.Merge(m, src)
}
func (m *QueryModuleAccountsResponse) XXX_Size() int {
return m.Size()
}
func (m *QueryModuleAccountsResponse) XXX_DiscardUnknown() {
xxx_messageInfo_QueryModuleAccountsResponse.DiscardUnknown(m)
}
var xxx_messageInfo_QueryModuleAccountsResponse proto.InternalMessageInfo
func (m *QueryModuleAccountsResponse) GetAccounts() []*types.Any {
if m != nil {
return m.Accounts
}
return nil
}
func init() {
proto.RegisterType((*QueryAccountsRequest)(nil), "cosmos.auth.v1beta1.QueryAccountsRequest")
proto.RegisterType((*QueryAccountsResponse)(nil), "cosmos.auth.v1beta1.QueryAccountsResponse")
@ -308,46 +390,52 @@ func init() {
proto.RegisterType((*QueryAccountResponse)(nil), "cosmos.auth.v1beta1.QueryAccountResponse")
proto.RegisterType((*QueryParamsRequest)(nil), "cosmos.auth.v1beta1.QueryParamsRequest")
proto.RegisterType((*QueryParamsResponse)(nil), "cosmos.auth.v1beta1.QueryParamsResponse")
proto.RegisterType((*QueryModuleAccountsRequest)(nil), "cosmos.auth.v1beta1.QueryModuleAccountsRequest")
proto.RegisterType((*QueryModuleAccountsResponse)(nil), "cosmos.auth.v1beta1.QueryModuleAccountsResponse")
}
func init() { proto.RegisterFile("cosmos/auth/v1beta1/query.proto", fileDescriptor_c451370b3929a27c) }
var fileDescriptor_c451370b3929a27c = []byte{
// 537 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x92, 0x41, 0x6b, 0x13, 0x4f,
0x18, 0xc6, 0x77, 0xda, 0xff, 0x3f, 0x89, 0x53, 0x4f, 0xd3, 0x08, 0x71, 0x6b, 0x77, 0xcb, 0x8a,
0x26, 0x29, 0x74, 0x86, 0xc6, 0x53, 0x45, 0x84, 0x46, 0x50, 0xbc, 0xc5, 0xc5, 0x93, 0x07, 0x65,
0x36, 0x19, 0xb7, 0x41, 0xb3, 0xb3, 0xcd, 0xec, 0x8a, 0x41, 0x04, 0xf1, 0xd4, 0x9b, 0x82, 0x5f,
0x20, 0x37, 0xbf, 0x80, 0x1f, 0xa2, 0x78, 0x2a, 0x78, 0xf1, 0x24, 0x92, 0x78, 0xf0, 0x63, 0x48,
0x66, 0xde, 0x89, 0x8d, 0xac, 0x26, 0xa7, 0xdd, 0x99, 0x79, 0x9f, 0xe7, 0xf9, 0xbd, 0xef, 0x0c,
0xf6, 0xbb, 0x52, 0x0d, 0xa4, 0x62, 0x3c, 0xcf, 0x8e, 0xd8, 0x8b, 0xfd, 0x48, 0x64, 0x7c, 0x9f,
0x1d, 0xe7, 0x62, 0x38, 0xa2, 0xe9, 0x50, 0x66, 0x92, 0x6c, 0x9a, 0x02, 0x3a, 0x2b, 0xa0, 0x50,
0xe0, 0xee, 0x82, 0x2a, 0xe2, 0x4a, 0x98, 0xea, 0xb9, 0x36, 0xe5, 0x71, 0x3f, 0xe1, 0x59, 0x5f,
0x26, 0xc6, 0xc0, 0xad, 0xc6, 0x32, 0x96, 0xfa, 0x97, 0xcd, 0xfe, 0x60, 0xf7, 0x72, 0x2c, 0x65,
0xfc, 0x5c, 0x30, 0xbd, 0x8a, 0xf2, 0xa7, 0x8c, 0x27, 0x90, 0xe8, 0x5e, 0x81, 0x23, 0x9e, 0xf6,
0x19, 0x4f, 0x12, 0x99, 0x69, 0x37, 0x05, 0xa7, 0x5e, 0x11, 0xb0, 0x86, 0x03, 0x63, 0x73, 0xfe,
0xc4, 0x24, 0x02, 0xbc, 0x5e, 0x04, 0x8f, 0x71, 0xf5, 0xc1, 0x8c, 0xf5, 0xb0, 0xdb, 0x95, 0x79,
0x92, 0xa9, 0x50, 0x1c, 0xe7, 0x42, 0x65, 0xe4, 0x2e, 0xc6, 0xbf, 0xa9, 0x6b, 0x68, 0x07, 0x35,
0x36, 0x5a, 0xd7, 0x29, 0x48, 0x67, 0x2d, 0x52, 0x33, 0x10, 0x48, 0xa3, 0x1d, 0x1e, 0x0b, 0xd0,
0x86, 0xe7, 0x94, 0xc1, 0x18, 0xe1, 0x4b, 0x7f, 0x04, 0xa8, 0x54, 0x26, 0x4a, 0x90, 0xdb, 0xb8,
0xc2, 0x61, 0xaf, 0x86, 0x76, 0xd6, 0x1b, 0x1b, 0xad, 0x2a, 0x35, 0x5d, 0x52, 0x3b, 0x00, 0x7a,
0x98, 0x8c, 0xda, 0x17, 0x3f, 0x7f, 0xda, 0xab, 0x80, 0xfa, 0x7e, 0x38, 0xd7, 0x90, 0x7b, 0x0b,
0x84, 0x6b, 0x9a, 0xb0, 0xbe, 0x94, 0xd0, 0x84, 0x2f, 0x20, 0x1e, 0xe0, 0xcd, 0xf3, 0x84, 0x76,
0x02, 0x35, 0x5c, 0xe6, 0xbd, 0xde, 0x50, 0x28, 0xa5, 0xdb, 0xbf, 0x10, 0xda, 0xe5, 0xcd, 0xca,
0xc9, 0xd8, 0x77, 0x7e, 0x8e, 0x7d, 0x27, 0x78, 0xb8, 0x38, 0xbd, 0x79, 0x6f, 0xb7, 0x70, 0x19,
0x38, 0x61, 0x74, 0xab, 0xb4, 0x66, 0x25, 0x41, 0x15, 0x13, 0xed, 0xda, 0xe1, 0x43, 0x3e, 0xb0,
0x37, 0x12, 0x74, 0x00, 0xd3, 0xee, 0x42, 0xd4, 0x01, 0x2e, 0xa5, 0x7a, 0x07, 0x92, 0xb6, 0x68,
0xc1, 0xe3, 0xa4, 0x46, 0xd4, 0xfe, 0xef, 0xf4, 0x9b, 0xef, 0x84, 0x20, 0x68, 0x7d, 0x5c, 0xc7,
0xff, 0x6b, 0x4b, 0x72, 0x82, 0xb0, 0xe5, 0x50, 0xa4, 0x59, 0xe8, 0x50, 0xf4, 0x4a, 0xdc, 0xdd,
0x55, 0x4a, 0x0d, 0x68, 0x70, 0xed, 0xed, 0x97, 0x1f, 0x1f, 0xd6, 0x7c, 0xb2, 0xcd, 0x0a, 0x5f,
0xab, 0x4d, 0x7f, 0x87, 0x70, 0x19, 0xb4, 0xa4, 0xb1, 0xd4, 0xde, 0x82, 0x34, 0x57, 0xa8, 0x04,
0x0e, 0xa6, 0x39, 0x9a, 0xa4, 0xfe, 0x4f, 0x0e, 0xf6, 0x0a, 0x6e, 0xfb, 0x35, 0x79, 0x83, 0x70,
0xc9, 0xcc, 0x8f, 0xd4, 0xff, 0x1e, 0xb3, 0x70, 0x59, 0x6e, 0x63, 0x79, 0x21, 0xe0, 0x5c, 0xd5,
0x38, 0xdb, 0x64, 0xab, 0x10, 0xc7, 0xdc, 0x54, 0xfb, 0xce, 0xe9, 0xc4, 0x43, 0x67, 0x13, 0x0f,
0x7d, 0x9f, 0x78, 0xe8, 0xfd, 0xd4, 0x73, 0xce, 0xa6, 0x9e, 0xf3, 0x75, 0xea, 0x39, 0x8f, 0x9a,
0x71, 0x3f, 0x3b, 0xca, 0x23, 0xda, 0x95, 0x03, 0x6b, 0x60, 0x3e, 0x7b, 0xaa, 0xf7, 0x8c, 0xbd,
0x34, 0x6e, 0xd9, 0x28, 0x15, 0x2a, 0x2a, 0xe9, 0xb7, 0x77, 0xe3, 0x57, 0x00, 0x00, 0x00, 0xff,
0xff, 0x2a, 0xe1, 0x81, 0xd3, 0xdf, 0x04, 0x00, 0x00,
// 602 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x93, 0x4f, 0x6b, 0x13, 0x41,
0x18, 0xc6, 0x77, 0x6b, 0x6d, 0xeb, 0x54, 0x3c, 0x4c, 0x23, 0xc4, 0x4d, 0xbb, 0x29, 0xab, 0x36,
0x49, 0x31, 0x33, 0x36, 0x9e, 0x2a, 0x22, 0x34, 0x8a, 0xe2, 0x41, 0x88, 0xc1, 0x93, 0x07, 0xcb,
0x24, 0x19, 0xb7, 0xc1, 0x66, 0x67, 0x9b, 0xd9, 0x15, 0x83, 0x08, 0xe2, 0xa9, 0x37, 0x05, 0xbf,
0x40, 0xfc, 0x0e, 0xfd, 0x10, 0xa5, 0x5e, 0x0a, 0x5e, 0x3c, 0x89, 0x24, 0x1e, 0xfc, 0x18, 0x92,
0x99, 0x77, 0x62, 0xb6, 0x6c, 0x4d, 0x4e, 0xd9, 0x99, 0x79, 0x9f, 0xf7, 0xf9, 0xbd, 0x7f, 0x82,
0xf2, 0x4d, 0x21, 0x3b, 0x42, 0x52, 0x16, 0x47, 0x7b, 0xf4, 0xcd, 0x56, 0x83, 0x47, 0x6c, 0x8b,
0x1e, 0xc4, 0xbc, 0xdb, 0x23, 0x61, 0x57, 0x44, 0x02, 0xaf, 0xe8, 0x00, 0x32, 0x0a, 0x20, 0x10,
0xe0, 0x6c, 0x82, 0xaa, 0xc1, 0x24, 0xd7, 0xd1, 0x63, 0x6d, 0xc8, 0xfc, 0x76, 0xc0, 0xa2, 0xb6,
0x08, 0x74, 0x02, 0x27, 0xe3, 0x0b, 0x5f, 0xa8, 0x4f, 0x3a, 0xfa, 0x82, 0xdb, 0x6b, 0xbe, 0x10,
0xfe, 0x3e, 0xa7, 0xea, 0xd4, 0x88, 0x5f, 0x51, 0x16, 0x80, 0xa3, 0xb3, 0x0a, 0x4f, 0x2c, 0x6c,
0x53, 0x16, 0x04, 0x22, 0x52, 0xd9, 0x24, 0xbc, 0xba, 0x69, 0xc0, 0x0a, 0x0e, 0x12, 0xeb, 0xf7,
0x5d, 0xed, 0x08, 0xf0, 0xea, 0xe0, 0xbd, 0x44, 0x99, 0x67, 0x23, 0xd6, 0x9d, 0x66, 0x53, 0xc4,
0x41, 0x24, 0xeb, 0xfc, 0x20, 0xe6, 0x32, 0xc2, 0x8f, 0x10, 0xfa, 0x47, 0x9d, 0xb5, 0xd7, 0xed,
0xe2, 0x72, 0x65, 0x83, 0x80, 0x74, 0x54, 0x22, 0xd1, 0x0d, 0x01, 0x37, 0x52, 0x63, 0x3e, 0x07,
0x6d, 0x7d, 0x42, 0xe9, 0xf5, 0x6d, 0x74, 0xf5, 0x8c, 0x81, 0x0c, 0x45, 0x20, 0x39, 0xbe, 0x8f,
0x96, 0x18, 0xdc, 0x65, 0xed, 0xf5, 0x0b, 0xc5, 0xe5, 0x4a, 0x86, 0xe8, 0x2a, 0x89, 0x69, 0x00,
0xd9, 0x09, 0x7a, 0xd5, 0xcb, 0x27, 0x47, 0xe5, 0x25, 0x50, 0x3f, 0xa9, 0x8f, 0x35, 0xf8, 0x71,
0x82, 0x70, 0x4e, 0x11, 0x16, 0xa6, 0x12, 0x6a, 0xf3, 0x04, 0xe2, 0x36, 0x5a, 0x99, 0x24, 0x34,
0x1d, 0xc8, 0xa2, 0x45, 0xd6, 0x6a, 0x75, 0xb9, 0x94, 0xaa, 0xfc, 0x4b, 0x75, 0x73, 0xbc, 0xbb,
0x74, 0xd8, 0xcf, 0x5b, 0x7f, 0xfa, 0x79, 0xcb, 0x7b, 0x9e, 0xec, 0xde, 0xb8, 0xb6, 0x7b, 0x68,
0x11, 0x38, 0xa1, 0x75, 0xb3, 0x94, 0x66, 0x24, 0x5e, 0x06, 0x61, 0x95, 0xb5, 0xc6, 0xba, 0xac,
0x63, 0x26, 0xe2, 0xd5, 0x00, 0xd3, 0xdc, 0x82, 0xd5, 0x36, 0x5a, 0x08, 0xd5, 0x0d, 0x38, 0xe5,
0x48, 0xca, 0x72, 0x12, 0x2d, 0xaa, 0xce, 0x1f, 0xff, 0xcc, 0x5b, 0x75, 0x10, 0x78, 0xab, 0xc8,
0x51, 0x19, 0x9f, 0x8a, 0x56, 0xbc, 0xcf, 0xcf, 0x6c, 0x80, 0xd7, 0x44, 0xb9, 0xd4, 0x57, 0xf0,
0x7d, 0x38, 0xe3, 0xf8, 0xf0, 0xc9, 0x51, 0xf9, 0x4a, 0x22, 0xc7, 0xc4, 0x10, 0x2b, 0xdf, 0xe6,
0xd1, 0x45, 0xe5, 0x82, 0x0f, 0x6d, 0x64, 0x5a, 0x21, 0x71, 0x29, 0xb5, 0x88, 0xb4, 0x45, 0x75,
0x36, 0x67, 0x09, 0xd5, 0xcc, 0xde, 0xcd, 0x8f, 0xdf, 0x7f, 0x7f, 0x99, 0xcb, 0xe3, 0x35, 0x9a,
0xfa, 0x87, 0x31, 0xee, 0x9f, 0x6c, 0xb4, 0x08, 0x5a, 0x5c, 0x9c, 0x9a, 0xde, 0x80, 0x94, 0x66,
0x88, 0x04, 0x0e, 0xaa, 0x38, 0x4a, 0xb8, 0xf0, 0x5f, 0x0e, 0xfa, 0x0e, 0x16, 0xee, 0x3d, 0xfe,
0x60, 0xa3, 0x05, 0x3d, 0x42, 0x5c, 0x38, 0xdf, 0x26, 0xb1, 0x2f, 0x4e, 0x71, 0x7a, 0x20, 0xe0,
0x5c, 0x57, 0x38, 0x6b, 0x38, 0x97, 0x8a, 0xa3, 0x97, 0x05, 0x7f, 0xb5, 0x51, 0x72, 0x8c, 0x12,
0xd3, 0xf3, 0x1d, 0x52, 0x57, 0xca, 0xb9, 0x3d, 0xbb, 0x00, 0xd0, 0x6e, 0x29, 0xb4, 0x0d, 0x7c,
0x23, 0x15, 0xad, 0xa3, 0x44, 0xbb, 0xa6, 0x61, 0xd5, 0x07, 0xc7, 0x03, 0xd7, 0x3e, 0x1d, 0xb8,
0xf6, 0xaf, 0x81, 0x6b, 0x7f, 0x1e, 0xba, 0xd6, 0xe9, 0xd0, 0xb5, 0x7e, 0x0c, 0x5d, 0xeb, 0x45,
0xc9, 0x6f, 0x47, 0x7b, 0x71, 0x83, 0x34, 0x45, 0xc7, 0x64, 0xd2, 0x3f, 0x65, 0xd9, 0x7a, 0x4d,
0xdf, 0xea, 0xb4, 0x51, 0x2f, 0xe4, 0xb2, 0xb1, 0xa0, 0xd6, 0xf7, 0xce, 0xdf, 0x00, 0x00, 0x00,
0xff, 0xff, 0xc0, 0xd9, 0x5e, 0x89, 0x06, 0x06, 0x00, 0x00,
}
// Reference imports to suppress errors if they are not otherwise used.
@ -368,6 +456,8 @@ type QueryClient interface {
Account(ctx context.Context, in *QueryAccountRequest, opts ...grpc.CallOption) (*QueryAccountResponse, error)
// Params queries all parameters.
Params(ctx context.Context, in *QueryParamsRequest, opts ...grpc.CallOption) (*QueryParamsResponse, error)
// ModuleAccounts returns all the existing Module Accounts.
ModuleAccounts(ctx context.Context, in *QueryModuleAccountsRequest, opts ...grpc.CallOption) (*QueryModuleAccountsResponse, error)
}
type queryClient struct {
@ -405,6 +495,15 @@ func (c *queryClient) Params(ctx context.Context, in *QueryParamsRequest, opts .
return out, nil
}
func (c *queryClient) ModuleAccounts(ctx context.Context, in *QueryModuleAccountsRequest, opts ...grpc.CallOption) (*QueryModuleAccountsResponse, error) {
out := new(QueryModuleAccountsResponse)
err := c.cc.Invoke(ctx, "/cosmos.auth.v1beta1.Query/ModuleAccounts", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// QueryServer is the server API for Query service.
type QueryServer interface {
// Accounts returns all the existing accounts
@ -413,6 +512,8 @@ type QueryServer interface {
Account(context.Context, *QueryAccountRequest) (*QueryAccountResponse, error)
// Params queries all parameters.
Params(context.Context, *QueryParamsRequest) (*QueryParamsResponse, error)
// ModuleAccounts returns all the existing Module Accounts.
ModuleAccounts(context.Context, *QueryModuleAccountsRequest) (*QueryModuleAccountsResponse, error)
}
// UnimplementedQueryServer can be embedded to have forward compatible implementations.
@ -428,6 +529,9 @@ func (*UnimplementedQueryServer) Account(ctx context.Context, req *QueryAccountR
func (*UnimplementedQueryServer) Params(ctx context.Context, req *QueryParamsRequest) (*QueryParamsResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method Params not implemented")
}
func (*UnimplementedQueryServer) ModuleAccounts(ctx context.Context, req *QueryModuleAccountsRequest) (*QueryModuleAccountsResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method ModuleAccounts not implemented")
}
func RegisterQueryServer(s grpc1.Server, srv QueryServer) {
s.RegisterService(&_Query_serviceDesc, srv)
@ -487,6 +591,24 @@ func _Query_Params_Handler(srv interface{}, ctx context.Context, dec func(interf
return interceptor(ctx, in, info, handler)
}
func _Query_ModuleAccounts_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(QueryModuleAccountsRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(QueryServer).ModuleAccounts(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/cosmos.auth.v1beta1.Query/ModuleAccounts",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(QueryServer).ModuleAccounts(ctx, req.(*QueryModuleAccountsRequest))
}
return interceptor(ctx, in, info, handler)
}
var _Query_serviceDesc = grpc.ServiceDesc{
ServiceName: "cosmos.auth.v1beta1.Query",
HandlerType: (*QueryServer)(nil),
@ -503,6 +625,10 @@ var _Query_serviceDesc = grpc.ServiceDesc{
MethodName: "Params",
Handler: _Query_Params_Handler,
},
{
MethodName: "ModuleAccounts",
Handler: _Query_ModuleAccounts_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "cosmos/auth/v1beta1/query.proto",
@ -713,6 +839,66 @@ func (m *QueryParamsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
return len(dAtA) - i, nil
}
func (m *QueryModuleAccountsRequest) 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 *QueryModuleAccountsRequest) MarshalTo(dAtA []byte) (int, error) {
size := m.Size()
return m.MarshalToSizedBuffer(dAtA[:size])
}
func (m *QueryModuleAccountsRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) {
i := len(dAtA)
_ = i
var l int
_ = l
return len(dAtA) - i, nil
}
func (m *QueryModuleAccountsResponse) 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 *QueryModuleAccountsResponse) MarshalTo(dAtA []byte) (int, error) {
size := m.Size()
return m.MarshalToSizedBuffer(dAtA[:size])
}
func (m *QueryModuleAccountsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
i := len(dAtA)
_ = i
var l int
_ = l
if len(m.Accounts) > 0 {
for iNdEx := len(m.Accounts) - 1; iNdEx >= 0; iNdEx-- {
{
size, err := m.Accounts[iNdEx].MarshalToSizedBuffer(dAtA[:i])
if err != nil {
return 0, err
}
i -= size
i = encodeVarintQuery(dAtA, i, uint64(size))
}
i--
dAtA[i] = 0xa
}
}
return len(dAtA) - i, nil
}
func encodeVarintQuery(dAtA []byte, offset int, v uint64) int {
offset -= sovQuery(v)
base := offset
@ -802,6 +988,30 @@ func (m *QueryParamsResponse) Size() (n int) {
return n
}
func (m *QueryModuleAccountsRequest) Size() (n int) {
if m == nil {
return 0
}
var l int
_ = l
return n
}
func (m *QueryModuleAccountsResponse) Size() (n int) {
if m == nil {
return 0
}
var l int
_ = l
if len(m.Accounts) > 0 {
for _, e := range m.Accounts {
l = e.Size()
n += 1 + l + sovQuery(uint64(l))
}
}
return n
}
func sovQuery(x uint64) (n int) {
return (math_bits.Len64(x|1) + 6) / 7
}
@ -1315,6 +1525,140 @@ func (m *QueryParamsResponse) Unmarshal(dAtA []byte) error {
}
return nil
}
func (m *QueryModuleAccountsRequest) 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: QueryModuleAccountsRequest: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: QueryModuleAccountsRequest: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
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 *QueryModuleAccountsResponse) 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: QueryModuleAccountsResponse: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: QueryModuleAccountsResponse: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Accounts", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowQuery
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
msglen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if msglen < 0 {
return ErrInvalidLengthQuery
}
postIndex := iNdEx + msglen
if postIndex < 0 {
return ErrInvalidLengthQuery
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Accounts = append(m.Accounts, &types.Any{})
if err := m.Accounts[len(m.Accounts)-1].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

View File

@ -139,6 +139,24 @@ func local_request_Query_Params_0(ctx context.Context, marshaler runtime.Marshal
}
func request_Query_ModuleAccounts_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq QueryModuleAccountsRequest
var metadata runtime.ServerMetadata
msg, err := client.ModuleAccounts(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return msg, metadata, err
}
func local_request_Query_ModuleAccounts_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq QueryModuleAccountsRequest
var metadata runtime.ServerMetadata
msg, err := server.ModuleAccounts(ctx, &protoReq)
return msg, metadata, err
}
// RegisterQueryHandlerServer registers the http handlers for service Query to "mux".
// UnaryRPC :call QueryServer directly.
// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.
@ -205,6 +223,26 @@ func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, serv
})
mux.Handle("GET", pattern_Query_ModuleAccounts_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := local_request_Query_ModuleAccounts_0(rctx, inboundMarshaler, server, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_Query_ModuleAccounts_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
return nil
}
@ -306,6 +344,26 @@ func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, clie
})
mux.Handle("GET", pattern_Query_ModuleAccounts_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateContext(ctx, mux, req)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := request_Query_ModuleAccounts_0(rctx, inboundMarshaler, client, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_Query_ModuleAccounts_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
return nil
}
@ -315,6 +373,8 @@ var (
pattern_Query_Account_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"cosmos", "auth", "v1beta1", "accounts", "address"}, "", runtime.AssumeColonVerbOpt(false)))
pattern_Query_Params_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"cosmos", "auth", "v1beta1", "params"}, "", runtime.AssumeColonVerbOpt(false)))
pattern_Query_ModuleAccounts_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"cosmos", "auth", "v1beta1", "module_accounts"}, "", runtime.AssumeColonVerbOpt(false)))
)
var (
@ -323,4 +383,6 @@ var (
forward_Query_Account_0 = runtime.ForwardResponseMessage
forward_Query_Params_0 = runtime.ForwardResponseMessage
forward_Query_ModuleAccounts_0 = runtime.ForwardResponseMessage
)

View File

@ -0,0 +1,97 @@
package capability_test
import (
"testing"
"github.com/stretchr/testify/suite"
abci "github.com/tendermint/tendermint/abci/types"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/simapp"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/module"
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
"github.com/cosmos/cosmos-sdk/x/capability"
"github.com/cosmos/cosmos-sdk/x/capability/keeper"
"github.com/cosmos/cosmos-sdk/x/capability/types"
)
type CapabilityTestSuite struct {
suite.Suite
cdc codec.Codec
ctx sdk.Context
app *simapp.SimApp
keeper *keeper.Keeper
module module.AppModule
}
func (suite *CapabilityTestSuite) SetupTest() {
checkTx := false
app := simapp.Setup(checkTx)
cdc := app.AppCodec()
// create new keeper so we can define custom scoping before init and seal
keeper := keeper.NewKeeper(cdc, app.GetKey(types.StoreKey), app.GetMemKey(types.MemStoreKey))
suite.app = app
suite.ctx = app.BaseApp.NewContext(checkTx, tmproto.Header{Height: 1})
suite.keeper = keeper
suite.cdc = cdc
suite.module = capability.NewAppModule(cdc, *keeper)
}
// The following test case mocks a specific bug discovered in https://github.com/cosmos/cosmos-sdk/issues/9800
// and ensures that the current code successfully fixes the issue.
func (suite *CapabilityTestSuite) TestInitializeMemStore() {
sk1 := suite.keeper.ScopeToModule(banktypes.ModuleName)
cap1, err := sk1.NewCapability(suite.ctx, "transfer")
suite.Require().NoError(err)
suite.Require().NotNil(cap1)
// mock statesync by creating new keeper that shares persistent state but loses in-memory map
newKeeper := keeper.NewKeeper(suite.cdc, suite.app.GetKey(types.StoreKey), suite.app.GetMemKey("testingkey"))
newSk1 := newKeeper.ScopeToModule(banktypes.ModuleName)
// Mock App startup
ctx := suite.app.BaseApp.NewUncachedContext(false, tmproto.Header{})
newKeeper.Seal()
suite.Require().False(newKeeper.IsInitialized(ctx), "memstore initialized flag set before BeginBlock")
// Mock app beginblock and ensure that no gas has been consumed and memstore is initialized
ctx = suite.app.BaseApp.NewContext(false, tmproto.Header{}).WithBlockGasMeter(sdk.NewGasMeter(50))
prevGas := ctx.BlockGasMeter().GasConsumed()
restartedModule := capability.NewAppModule(suite.cdc, *newKeeper)
restartedModule.BeginBlock(ctx, abci.RequestBeginBlock{})
suite.Require().True(newKeeper.IsInitialized(ctx), "memstore initialized flag not set")
gasUsed := ctx.BlockGasMeter().GasConsumed()
suite.Require().Equal(prevGas, gasUsed, "beginblocker consumed gas during execution")
// Mock the first transaction getting capability and subsequently failing
// by using a cached context and discarding all cached writes.
cacheCtx, _ := ctx.CacheContext()
_, ok := newSk1.GetCapability(cacheCtx, "transfer")
suite.Require().True(ok)
// Ensure that the second transaction can still receive capability even if first tx fails.
ctx = suite.app.BaseApp.NewContext(false, tmproto.Header{})
cap1, ok = newSk1.GetCapability(ctx, "transfer")
suite.Require().True(ok)
// Ensure the capabilities don't get reinitialized on next BeginBlock
// by testing to see if capability returns same pointer
// also check that initialized flag is still set
restartedModule.BeginBlock(ctx, abci.RequestBeginBlock{})
recap, ok := newSk1.GetCapability(ctx, "transfer")
suite.Require().True(ok)
suite.Require().Equal(cap1, recap, "capabilities got reinitialized after second BeginBlock")
suite.Require().True(newKeeper.IsInitialized(ctx), "memstore initialized flag not set")
}
func TestCapabilityTestSuite(t *testing.T) {
suite.Run(t, new(CapabilityTestSuite))
}

View File

@ -13,11 +13,12 @@ func InitGenesis(ctx sdk.Context, k keeper.Keeper, genState types.GenesisState)
panic(err)
}
// set owners for each index and initialize capability
// set owners for each index
for _, genOwner := range genState.Owners {
k.SetOwners(ctx, genOwner.Index, genOwner.IndexOwners)
k.InitializeCapability(ctx, genOwner.Index, genOwner.IndexOwners)
}
// initialize in-memory capabilities
k.InitMemStore(ctx)
}
// ExportGenesis returns the capability module's exported genesis.

View File

@ -0,0 +1,59 @@
package capability_test
import (
"github.com/tendermint/tendermint/libs/log"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
dbm "github.com/tendermint/tm-db"
"github.com/cosmos/cosmos-sdk/simapp"
sdk "github.com/cosmos/cosmos-sdk/types"
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
"github.com/cosmos/cosmos-sdk/x/capability"
"github.com/cosmos/cosmos-sdk/x/capability/keeper"
"github.com/cosmos/cosmos-sdk/x/capability/types"
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
)
func (suite *CapabilityTestSuite) TestGenesis() {
sk1 := suite.keeper.ScopeToModule(banktypes.ModuleName)
sk2 := suite.keeper.ScopeToModule(stakingtypes.ModuleName)
cap1, err := sk1.NewCapability(suite.ctx, "transfer")
suite.Require().NoError(err)
suite.Require().NotNil(cap1)
err = sk2.ClaimCapability(suite.ctx, cap1, "transfer")
suite.Require().NoError(err)
cap2, err := sk2.NewCapability(suite.ctx, "ica")
suite.Require().NoError(err)
suite.Require().NotNil(cap2)
genState := capability.ExportGenesis(suite.ctx, *suite.keeper)
// create new app that does not share persistent or in-memory state
// and initialize app from exported genesis state above.
db := dbm.NewMemDB()
encCdc := simapp.MakeTestEncodingConfig()
newApp := simapp.NewSimApp(log.NewNopLogger(), db, nil, true, map[int64]bool{}, simapp.DefaultNodeHome, 5, encCdc, simapp.EmptyAppOptions{})
newKeeper := keeper.NewKeeper(suite.cdc, newApp.GetKey(types.StoreKey), newApp.GetMemKey(types.MemStoreKey))
newSk1 := newKeeper.ScopeToModule(banktypes.ModuleName)
newSk2 := newKeeper.ScopeToModule(stakingtypes.ModuleName)
deliverCtx, _ := newApp.BaseApp.NewUncachedContext(false, tmproto.Header{}).WithBlockGasMeter(sdk.NewInfiniteGasMeter()).CacheContext()
capability.InitGenesis(deliverCtx, *newKeeper, *genState)
// check that all previous capabilities exist in new app after InitGenesis
sk1Cap1, ok := newSk1.GetCapability(deliverCtx, "transfer")
suite.Require().True(ok, "could not get first capability after genesis on first ScopedKeeper")
suite.Require().Equal(*cap1, *sk1Cap1, "capability values not equal on first ScopedKeeper")
sk2Cap1, ok := newSk2.GetCapability(deliverCtx, "transfer")
suite.Require().True(ok, "could not get first capability after genesis on first ScopedKeeper")
suite.Require().Equal(*cap1, *sk2Cap1, "capability values not equal on first ScopedKeeper")
sk2Cap2, ok := newSk2.GetCapability(deliverCtx, "ica")
suite.Require().True(ok, "could not get second capability after genesis on second ScopedKeeper")
suite.Require().Equal(*cap2, *sk2Cap2, "capability values not equal on second ScopedKeeper")
}

View File

@ -13,14 +13,6 @@ import (
"github.com/cosmos/cosmos-sdk/x/capability/types"
)
// initialized is a global variable used by GetCapability to ensure that the memory store
// and capability map are correctly populated. A state-synced node may copy over all the persistent
// state and start running the application without having the in-memory state required for x/capability.
// Thus, we must initialized the memory stores on-the-fly during tx execution once the first GetCapability
// is called.
// This is a temporary fix and should be replaced by a more robust solution in the next breaking release.
var initialized = false
type (
// Keeper defines the capability module's keeper. It is responsible for provisioning,
// tracking, and authenticating capabilities at runtime. During application
@ -97,15 +89,22 @@ func (k *Keeper) ScopeToModule(moduleName string) ScopedKeeper {
}
}
// InitializeAndSeal loads all capabilities from the persistent KVStore into the
// in-memory store and seals the keeper to prevent further modules from creating
// a scoped keeper. InitializeAndSeal must be called once after the application
// state is loaded.
func (k *Keeper) InitializeAndSeal(ctx sdk.Context) {
// Seal seals the keeper to prevent further modules from creating a scoped keeper.
// Seal may be called during app initialization for applications that do not wish to create scoped keepers dynamically.
func (k *Keeper) Seal() {
if k.sealed {
panic("cannot initialize and seal an already sealed capability keeper")
}
k.sealed = true
}
// InitMemStore will assure that the module store is a memory store (it will panic if it's not)
// and willl initialize it. The function is safe to be called multiple times.
// InitMemStore must be called every time the app starts before the keeper is used (so
// `BeginBlock` or `InitChain` - whichever is first). We need access to the store so we
// can't initialize it in a constructor.
func (k *Keeper) InitMemStore(ctx sdk.Context) {
memStore := ctx.KVStore(k.memKey)
memStoreType := memStore.GetStoreType()
@ -113,22 +112,36 @@ func (k *Keeper) InitializeAndSeal(ctx sdk.Context) {
panic(fmt.Sprintf("invalid memory store type; got %s, expected: %s", memStoreType, sdk.StoreTypeMemory))
}
prefixStore := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefixIndexCapability)
iterator := sdk.KVStorePrefixIterator(prefixStore, nil)
// create context with no block gas meter to ensure we do not consume gas during local initialization logic.
noGasCtx := ctx.WithBlockGasMeter(sdk.NewInfiniteGasMeter())
// initialize the in-memory store for all persisted capabilities
defer iterator.Close()
// check if memory store has not been initialized yet by checking if initialized flag is nil.
if !k.IsInitialized(noGasCtx) {
prefixStore := prefix.NewStore(noGasCtx.KVStore(k.storeKey), types.KeyPrefixIndexCapability)
iterator := sdk.KVStorePrefixIterator(prefixStore, nil)
for ; iterator.Valid(); iterator.Next() {
index := types.IndexFromKey(iterator.Key())
// initialize the in-memory store for all persisted capabilities
defer iterator.Close()
var capOwners types.CapabilityOwners
for ; iterator.Valid(); iterator.Next() {
index := types.IndexFromKey(iterator.Key())
k.cdc.MustUnmarshal(iterator.Value(), &capOwners)
k.InitializeCapability(ctx, index, capOwners)
var capOwners types.CapabilityOwners
k.cdc.MustUnmarshal(iterator.Value(), &capOwners)
k.InitializeCapability(noGasCtx, index, capOwners)
}
// set the initialized flag so we don't rerun initialization logic
memStore := noGasCtx.KVStore(k.memKey)
memStore.Set(types.KeyMemInitialized, []byte{1})
}
}
k.sealed = true
// IsInitialized returns true if the keeper is properly initialized, and false otherwise.
func (k *Keeper) IsInitialized(ctx sdk.Context) bool {
memStore := ctx.KVStore(k.memKey)
return memStore.Get(types.KeyMemInitialized) != nil
}
// InitializeIndex sets the index to one (or greater) in InitChain according
@ -350,22 +363,6 @@ func (sk ScopedKeeper) ReleaseCapability(ctx sdk.Context, cap *types.Capability)
// by name. The module is not allowed to retrieve capabilities which it does not
// own.
func (sk ScopedKeeper) GetCapability(ctx sdk.Context, name string) (*types.Capability, bool) {
// Create a keeper that will set all in-memory mappings correctly into memstore and capmap if scoped keeper is not initialized yet.
// This ensures that the in-memory mappings are correctly filled in, in case this is a state-synced node.
// This is a temporary non-breaking fix, a future PR should store the reverse mapping in the persistent store and reconstruct forward mapping and capmap on the fly.
if !initialized {
// create context with infinite gas meter to avoid app state mismatch.
initCtx := ctx.WithGasMeter(sdk.NewInfiniteGasMeter())
k := Keeper{
cdc: sk.cdc,
storeKey: sk.storeKey,
memKey: sk.memKey,
capMap: sk.capMap,
}
k.InitializeAndSeal(initCtx)
initialized = true
}
if strings.TrimSpace(name) == "" {
return nil, false
}

View File

@ -36,7 +36,7 @@ func (suite *KeeperTestSuite) SetupTest() {
suite.keeper = keeper
}
func (suite *KeeperTestSuite) TestInitializeAndSeal() {
func (suite *KeeperTestSuite) TestSeal() {
sk := suite.keeper.ScopeToModule(banktypes.ModuleName)
suite.Require().Panics(func() {
suite.keeper.ScopeToModule(" ")
@ -56,7 +56,7 @@ func (suite *KeeperTestSuite) TestInitializeAndSeal() {
}
suite.Require().NotPanics(func() {
suite.keeper.InitializeAndSeal(suite.ctx)
suite.keeper.Seal()
})
for i, cap := range caps {
@ -67,7 +67,7 @@ func (suite *KeeperTestSuite) TestInitializeAndSeal() {
}
suite.Require().Panics(func() {
suite.keeper.InitializeAndSeal(suite.ctx)
suite.keeper.Seal()
})
suite.Require().Panics(func() {

View File

@ -4,6 +4,7 @@ import (
"encoding/json"
"fmt"
"math/rand"
"time"
"github.com/gorilla/mux"
"github.com/grpc-ecosystem/grpc-gateway/runtime"
@ -14,6 +15,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/telemetry"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/module"
simtypes "github.com/cosmos/cosmos-sdk/types/simulation"
@ -143,7 +145,13 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONCodec) json.Raw
func (AppModule) ConsensusVersion() uint64 { return 1 }
// BeginBlock executes all ABCI BeginBlock logic respective to the capability module.
func (am AppModule) BeginBlock(_ sdk.Context, _ abci.RequestBeginBlock) {}
// BeginBlocker calls InitMemStore to assert that the memory store is initialized.
// It's safe to run multiple times.
func (am AppModule) BeginBlock(ctx sdk.Context, _ abci.RequestBeginBlock) {
defer telemetry.ModuleMeasureSince(types.ModuleName, time.Now(), telemetry.MetricKeyBeginBlocker)
am.keeper.InitMemStore(ctx)
}
// EndBlock executes all ABCI EndBlock logic respective to the capability module. It
// returns no validator updates.

View File

@ -25,6 +25,9 @@ var (
// KeyPrefixIndexCapability defines a key prefix that stores index to capability
// name mappings.
KeyPrefixIndexCapability = []byte("capability_index")
// KeyMemInitialized defines the key that stores the initialized flag in the memory store
KeyMemInitialized = []byte("mem_initialized")
)
// RevCapabilityKey returns a reverse lookup key for a given module and capability

View File

@ -77,10 +77,9 @@ $ %s gentx my-key-name 1000000stake --home=/path/to/home/dir --keyring-backend=o
}
// read --pubkey, if empty take it from priv_validator.json
if val, _ := cmd.Flags().GetString(cli.FlagPubKey); val != "" {
err = clientCtx.Codec.UnmarshalJSON([]byte(val), valPubKey)
if err != nil {
return errors.Wrap(err, "failed to unmarshal consensus node public key")
if pkStr, _ := cmd.Flags().GetString(cli.FlagPubKey); pkStr != "" {
if err := clientCtx.Codec.UnmarshalInterfaceJSON([]byte(pkStr), &valPubKey); err != nil {
return errors.Wrap(err, "failed to unmarshal validator public key")
}
}

View File

@ -46,8 +46,7 @@ func TestInitCmd(t *testing.T) {
}
},
shouldErr: false,
err: nil,
err: nil,
},
}

View File

@ -17,6 +17,7 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
"github.com/cosmos/cosmos-sdk/x/genutil/client/cli"
stakingcli "github.com/cosmos/cosmos-sdk/x/staking/client/cli"
"github.com/cosmos/cosmos-sdk/x/staking/types"
)
@ -89,6 +90,44 @@ func (s *IntegrationTestSuite) TestGenTxCmd() {
s.Require().Equal(sdk.MsgTypeURL(&types.MsgCreateValidator{}), sdk.MsgTypeURL(msgs[0]))
s.Require().Equal([]string{val.Address.String()}, msgs[0].GetSigners())
s.Require().Equal(amount, msgs[0].(*types.MsgCreateValidator).Value)
err = tx.ValidateBasic()
s.Require().NoError(err)
s.Require().NoError(tx.ValidateBasic())
}
func (s *IntegrationTestSuite) TestGenTxCmdPubkey() {
val := s.network.Validators[0]
dir := s.T().TempDir()
cmd := cli.GenTxCmd(
simapp.ModuleBasics,
val.ClientCtx.TxConfig,
banktypes.GenesisBalancesIterator{},
val.ClientCtx.HomeDir,
)
_, out := testutil.ApplyMockIO(cmd)
clientCtx := val.ClientCtx.WithOutput(out)
ctx := context.Background()
ctx = context.WithValue(ctx, client.ClientContextKey, &clientCtx)
amount := sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(12))
genTxFile := filepath.Join(dir, "myTx")
cmd.SetArgs([]string{
fmt.Sprintf("--%s=%s", flags.FlagChainID, s.network.Config.ChainID),
fmt.Sprintf("--%s=%s", flags.FlagOutputDocument, genTxFile),
fmt.Sprintf("--%s={\"key\":\"BOIkjkFruMpfOFC9oNPhiJGfmY2pHF/gwHdLDLnrnS0=\"}", stakingcli.FlagPubKey),
val.Moniker,
amount.String(),
})
s.Require().Error(cmd.ExecuteContext(ctx))
cmd.SetArgs([]string{
fmt.Sprintf("--%s=%s", flags.FlagChainID, s.network.Config.ChainID),
fmt.Sprintf("--%s=%s", flags.FlagOutputDocument, genTxFile),
fmt.Sprintf("--%s={\"@type\":\"/cosmos.crypto.ed25519.PubKey\",\"key\":\"BOIkjkFruMpfOFC9oNPhiJGfmY2pHF/gwHdLDLnrnS0=\"}", stakingcli.FlagPubKey),
val.Moniker,
amount.String(),
})
s.Require().NoError(cmd.ExecuteContext(ctx))
}

View File

@ -75,7 +75,7 @@ func FlagSetAmount() *flag.FlagSet {
// FlagSetPublicKey Returns the flagset for Public Key related operations.
func FlagSetPublicKey() *flag.FlagSet {
fs := flag.NewFlagSet("", flag.ContinueOnError)
fs.String(FlagPubKey, "", "The Bech32 encoded PubKey of the validator")
fs.String(FlagPubKey, "", "The validator's Protobuf JSON encoded public key")
return fs
}

View File

@ -212,6 +212,15 @@ func (s *IntegrationTestSuite) TestNewCreateValidatorCmd() {
txResp := tc.respType.(*sdk.TxResponse)
require.Equal(tc.expectedCode, txResp.Code,
"test: %s, output\n:", tc.name, out.String())
events := txResp.Logs[0].GetEvents()
for i := 0; i < len(events); i++ {
if events[i].GetType() == "create_validator" {
attributes := events[i].GetAttributes()
require.Equal(attributes[1].Value, "100stake")
break
}
}
}
})
}

View File

@ -112,7 +112,7 @@ func (k msgServer) CreateValidator(goCtx context.Context, msg *types.MsgCreateVa
sdk.NewEvent(
types.EventTypeCreateValidator,
sdk.NewAttribute(types.AttributeKeyValidator, msg.ValidatorAddress),
sdk.NewAttribute(sdk.AttributeKeyAmount, msg.Value.Amount.String()),
sdk.NewAttribute(sdk.AttributeKeyAmount, msg.Value.String()),
),
sdk.NewEvent(
sdk.EventTypeMessage,
@ -235,7 +235,7 @@ func (k msgServer) Delegate(goCtx context.Context, msg *types.MsgDelegate) (*typ
sdk.NewEvent(
types.EventTypeDelegate,
sdk.NewAttribute(types.AttributeKeyValidator, msg.ValidatorAddress),
sdk.NewAttribute(sdk.AttributeKeyAmount, msg.Amount.Amount.String()),
sdk.NewAttribute(sdk.AttributeKeyAmount, msg.Amount.String()),
sdk.NewAttribute(types.AttributeKeyNewShares, newShares.String()),
),
sdk.NewEvent(
@ -301,7 +301,7 @@ func (k msgServer) BeginRedelegate(goCtx context.Context, msg *types.MsgBeginRed
types.EventTypeRedelegate,
sdk.NewAttribute(types.AttributeKeySrcValidator, msg.ValidatorSrcAddress),
sdk.NewAttribute(types.AttributeKeyDstValidator, msg.ValidatorDstAddress),
sdk.NewAttribute(sdk.AttributeKeyAmount, msg.Amount.Amount.String()),
sdk.NewAttribute(sdk.AttributeKeyAmount, msg.Amount.String()),
sdk.NewAttribute(types.AttributeKeyCompletionTime, completionTime.Format(time.RFC3339)),
),
sdk.NewEvent(
@ -362,7 +362,7 @@ func (k msgServer) Undelegate(goCtx context.Context, msg *types.MsgUndelegate) (
sdk.NewEvent(
types.EventTypeUnbond,
sdk.NewAttribute(types.AttributeKeyValidator, msg.ValidatorAddress),
sdk.NewAttribute(sdk.AttributeKeyAmount, msg.Amount.Amount.String()),
sdk.NewAttribute(sdk.AttributeKeyAmount, msg.Amount.String()),
sdk.NewAttribute(types.AttributeKeyCompletionTime, completionTime.Format(time.RFC3339)),
),
sdk.NewEvent(