feat: implement x/params get all subspaces/keys (#9884)

This commit is contained in:
Aleksandr Bezobchuk 2021-08-10 08:44:58 -04:00 committed by GitHub
parent 47a3f02735
commit 055e7e8d80
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 876 additions and 28 deletions

View File

@ -39,6 +39,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
### Features
* [\#9884](https://github.com/cosmos/cosmos-sdk/pull/9884) Provide a new gRPC query handler, `/cosmos/params/v1beta1/subspaces`, that allows the ability to query for all registered subspaces and their respective keys.
* [\#9860](https://github.com/cosmos/cosmos-sdk/pull/9860) Emit transaction fee in ante handler fee decorator. The event type is `tx` and the attribute is `fee`.
* [\#9776](https://github.com/cosmos/cosmos-sdk/pull/9776) Add flag `staking-bond-denom` to specify the staking bond denomination value when initializing a new chain.
* [\#9533](https://github.com/cosmos/cosmos-sdk/pull/9533) Added a new gRPC method, `DenomOwners`, in `x/bank` to query for all account holders of a specific denomination.

View File

@ -483,6 +483,9 @@
- [cosmos/params/v1beta1/query.proto](#cosmos/params/v1beta1/query.proto)
- [QueryParamsRequest](#cosmos.params.v1beta1.QueryParamsRequest)
- [QueryParamsResponse](#cosmos.params.v1beta1.QueryParamsResponse)
- [QuerySubspacesRequest](#cosmos.params.v1beta1.QuerySubspacesRequest)
- [QuerySubspacesResponse](#cosmos.params.v1beta1.QuerySubspacesResponse)
- [Subspace](#cosmos.params.v1beta1.Subspace)
- [Query](#cosmos.params.v1beta1.Query)
@ -966,7 +969,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|
| `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 -->
@ -6957,6 +6960,50 @@ QueryParamsResponse is response type for the Query/Params RPC method.
<a name="cosmos.params.v1beta1.QuerySubspacesRequest"></a>
### QuerySubspacesRequest
QuerySubspacesRequest defines a request type for querying for all registered
subspaces and all keys for a subspace.
<a name="cosmos.params.v1beta1.QuerySubspacesResponse"></a>
### QuerySubspacesResponse
QuerySubspacesResponse defines the response types for querying for all
registered subspaces and all keys for a subspace.
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `subspaces` | [Subspace](#cosmos.params.v1beta1.Subspace) | repeated | |
<a name="cosmos.params.v1beta1.Subspace"></a>
### Subspace
Subspace defines a parameter subspace name and all the keys that exist for
the subspace.
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `subspace` | [string](#string) | | |
| `keys` | [string](#string) | repeated | |
<!-- end messages -->
<!-- end enums -->
@ -6972,6 +7019,7 @@ Query defines the gRPC querier service.
| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint |
| ----------- | ------------ | ------------- | ------------| ------- | -------- |
| `Params` | [QueryParamsRequest](#cosmos.params.v1beta1.QueryParamsRequest) | [QueryParamsResponse](#cosmos.params.v1beta1.QueryParamsResponse) | Params queries a specific parameter of a module, given its subspace and key. | GET|/cosmos/params/v1beta1/params|
| `Subspaces` | [QuerySubspacesRequest](#cosmos.params.v1beta1.QuerySubspacesRequest) | [QuerySubspacesResponse](#cosmos.params.v1beta1.QuerySubspacesResponse) | Subspaces queries for all registered subspaces and all keys for a subspace. | GET|/cosmos/params/v1beta1/subspaces|
<!-- end services -->

View File

@ -14,6 +14,11 @@ service Query {
rpc Params(QueryParamsRequest) returns (QueryParamsResponse) {
option (google.api.http).get = "/cosmos/params/v1beta1/params";
}
// Subspaces queries for all registered subspaces and all keys for a subspace.
rpc Subspaces(QuerySubspacesRequest) returns (QuerySubspacesResponse) {
option (google.api.http).get = "/cosmos/params/v1beta1/subspaces";
}
}
// QueryParamsRequest is request type for the Query/Params RPC method.
@ -30,3 +35,20 @@ message QueryParamsResponse {
// param defines the queried parameter.
ParamChange param = 1 [(gogoproto.nullable) = false];
}
// QuerySubspacesRequest defines a request type for querying for all registered
// subspaces and all keys for a subspace.
message QuerySubspacesRequest {}
// QuerySubspacesResponse defines the response types for querying for all
// registered subspaces and all keys for a subspace.
message QuerySubspacesResponse {
repeated Subspace subspaces = 1;
}
// Subspace defines a parameter subspace name and all the keys that exist for
// the subspace.
message Subspace {
string subspace = 1;
repeated string keys = 2;
}

View File

@ -456,7 +456,7 @@ 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 returns all the existing module accounts.
ModuleAccounts(ctx context.Context, in *QueryModuleAccountsRequest, opts ...grpc.CallOption) (*QueryModuleAccountsResponse, error)
}
@ -512,7 +512,7 @@ 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 returns all the existing module accounts.
ModuleAccounts(context.Context, *QueryModuleAccountsRequest) (*QueryModuleAccountsResponse, error)
}

View File

@ -567,9 +567,9 @@ type Proposal struct {
Result Proposal_Result `protobuf:"varint,9,opt,name=result,proto3,enum=cosmos.group.v1beta1.Proposal_Result" json:"result,omitempty"`
// vote_state contains the sums of all weighted votes for this proposal.
VoteState Tally `protobuf:"bytes,10,opt,name=vote_state,json=voteState,proto3" json:"vote_state"`
// timeout is the timestamp of the block where the proposal execution times out. Header times of the votes and execution messages
// must be before this end time to be included in the election. After the timeout timestamp the proposal can not be
// executed anymore and should be considered pending delete.
// timeout is the timestamp of the block where the proposal execution times out. Header times of the votes and
// execution messages must be before this end time to be included in the election. After the timeout timestamp the
// proposal can not be executed anymore and should be considered pending delete.
Timeout time.Time `protobuf:"bytes,11,opt,name=timeout,proto3,stdtime" json:"timeout"`
// executor_result is the final result based on the votes and election rule. Initial value is NotRun.
ExecutorResult Proposal_ExecutorResult `protobuf:"varint,12,opt,name=executor_result,json=executorResult,proto3,enum=cosmos.group.v1beta1.Proposal_ExecutorResult" json:"executor_result,omitempty"`

View File

@ -34,3 +34,36 @@ func (k Keeper) Params(c context.Context, req *proposal.QueryParamsRequest) (*pr
return &proposal.QueryParamsResponse{Param: param}, nil
}
// Subspaces implements the gRPC query handler for fetching all registered
// subspaces and all the keys for each subspace.
func (k Keeper) Subspaces(
goCtx context.Context,
req *proposal.QuerySubspacesRequest,
) (*proposal.QuerySubspacesResponse, error) {
if req == nil {
return nil, status.Errorf(codes.InvalidArgument, "empty request")
}
spaces := k.GetSubspaces()
resp := &proposal.QuerySubspacesResponse{
Subspaces: make([]*proposal.Subspace, len(spaces)),
}
ctx := sdk.UnwrapSDKContext(goCtx)
for i, ss := range spaces {
var keys []string
ss.IterateKeys(ctx, func(key []byte) bool {
keys = append(keys, string(key))
return false
})
resp.Subspaces[i] = &proposal.Subspace{
Subspace: ss.Name(),
Keys: keys,
}
}
return resp, nil
}

View File

@ -84,3 +84,24 @@ func (suite *KeeperTestSuite) TestGRPCQueryParams() {
})
}
}
func (suite *KeeperTestSuite) TestGRPCQuerySubspaces() {
ctx := sdk.WrapSDKContext(suite.ctx)
// NOTE: Each subspace will not have any keys that we can check against
// because InitGenesis has not been called during app construction.
resp, err := suite.queryClient.Subspaces(ctx, &proposal.QuerySubspacesRequest{})
suite.Require().NoError(err)
suite.Require().NotNil(resp)
spaces := make([]string, len(resp.Subspaces))
i := 0
for _, ss := range resp.Subspaces {
spaces[i] = ss.Subspace
i++
}
// require the response contains a few subspaces we know exist
suite.Require().Contains(spaces, "bank")
suite.Require().Contains(spaces, "staking")
}

View File

@ -59,3 +59,15 @@ func (k Keeper) GetSubspace(s string) (types.Subspace, bool) {
}
return *space, ok
}
// GetSubspaces returns all the registered subspaces.
func (k Keeper) GetSubspaces() []types.Subspace {
spaces := make([]types.Subspace, len(k.spaces))
i := 0
for _, ss := range k.spaces {
spaces[i] = *ss
i++
}
return spaces
}

View File

@ -148,6 +148,29 @@ func indirect(ptr interface{}) interface{} {
return reflect.ValueOf(ptr).Elem().Interface()
}
func TestGetSubspaces(t *testing.T) {
_, _, _, _, keeper := testComponents()
table := types.NewKeyTable(
types.NewParamSetPair([]byte("string"), "", validateNoOp),
types.NewParamSetPair([]byte("bool"), false, validateNoOp),
)
_ = keeper.Subspace("key1").WithKeyTable(table)
_ = keeper.Subspace("key2").WithKeyTable(table)
spaces := keeper.GetSubspaces()
require.Len(t, spaces, 2)
var names []string
for _, ss := range spaces {
names = append(names, ss.Name())
}
require.Contains(t, names, "key1")
require.Contains(t, names, "key2")
}
func TestSubspace(t *testing.T) {
cdc, ctx, key, _, keeper := testComponents()

View File

@ -130,36 +130,182 @@ func (m *QueryParamsResponse) GetParam() ParamChange {
return ParamChange{}
}
// QuerySubspacesRequest defines a request type for querying for all registered
// subspaces and all keys for a subspace.
type QuerySubspacesRequest struct {
}
func (m *QuerySubspacesRequest) Reset() { *m = QuerySubspacesRequest{} }
func (m *QuerySubspacesRequest) String() string { return proto.CompactTextString(m) }
func (*QuerySubspacesRequest) ProtoMessage() {}
func (*QuerySubspacesRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_2b32979c1792ccc4, []int{2}
}
func (m *QuerySubspacesRequest) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *QuerySubspacesRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
if deterministic {
return xxx_messageInfo_QuerySubspacesRequest.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 *QuerySubspacesRequest) XXX_Merge(src proto.Message) {
xxx_messageInfo_QuerySubspacesRequest.Merge(m, src)
}
func (m *QuerySubspacesRequest) XXX_Size() int {
return m.Size()
}
func (m *QuerySubspacesRequest) XXX_DiscardUnknown() {
xxx_messageInfo_QuerySubspacesRequest.DiscardUnknown(m)
}
var xxx_messageInfo_QuerySubspacesRequest proto.InternalMessageInfo
// QuerySubspacesResponse defines the response types for querying for all
// registered subspaces and all keys for a subspace.
type QuerySubspacesResponse struct {
Subspaces []*Subspace `protobuf:"bytes,1,rep,name=subspaces,proto3" json:"subspaces,omitempty"`
}
func (m *QuerySubspacesResponse) Reset() { *m = QuerySubspacesResponse{} }
func (m *QuerySubspacesResponse) String() string { return proto.CompactTextString(m) }
func (*QuerySubspacesResponse) ProtoMessage() {}
func (*QuerySubspacesResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_2b32979c1792ccc4, []int{3}
}
func (m *QuerySubspacesResponse) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *QuerySubspacesResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
if deterministic {
return xxx_messageInfo_QuerySubspacesResponse.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 *QuerySubspacesResponse) XXX_Merge(src proto.Message) {
xxx_messageInfo_QuerySubspacesResponse.Merge(m, src)
}
func (m *QuerySubspacesResponse) XXX_Size() int {
return m.Size()
}
func (m *QuerySubspacesResponse) XXX_DiscardUnknown() {
xxx_messageInfo_QuerySubspacesResponse.DiscardUnknown(m)
}
var xxx_messageInfo_QuerySubspacesResponse proto.InternalMessageInfo
func (m *QuerySubspacesResponse) GetSubspaces() []*Subspace {
if m != nil {
return m.Subspaces
}
return nil
}
// Subspace defines a parameter subspace name and all the keys that exist for
// the subspace.
type Subspace struct {
Subspace string `protobuf:"bytes,1,opt,name=subspace,proto3" json:"subspace,omitempty"`
Keys []string `protobuf:"bytes,2,rep,name=keys,proto3" json:"keys,omitempty"`
}
func (m *Subspace) Reset() { *m = Subspace{} }
func (m *Subspace) String() string { return proto.CompactTextString(m) }
func (*Subspace) ProtoMessage() {}
func (*Subspace) Descriptor() ([]byte, []int) {
return fileDescriptor_2b32979c1792ccc4, []int{4}
}
func (m *Subspace) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *Subspace) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
if deterministic {
return xxx_messageInfo_Subspace.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 *Subspace) XXX_Merge(src proto.Message) {
xxx_messageInfo_Subspace.Merge(m, src)
}
func (m *Subspace) XXX_Size() int {
return m.Size()
}
func (m *Subspace) XXX_DiscardUnknown() {
xxx_messageInfo_Subspace.DiscardUnknown(m)
}
var xxx_messageInfo_Subspace proto.InternalMessageInfo
func (m *Subspace) GetSubspace() string {
if m != nil {
return m.Subspace
}
return ""
}
func (m *Subspace) GetKeys() []string {
if m != nil {
return m.Keys
}
return nil
}
func init() {
proto.RegisterType((*QueryParamsRequest)(nil), "cosmos.params.v1beta1.QueryParamsRequest")
proto.RegisterType((*QueryParamsResponse)(nil), "cosmos.params.v1beta1.QueryParamsResponse")
proto.RegisterType((*QuerySubspacesRequest)(nil), "cosmos.params.v1beta1.QuerySubspacesRequest")
proto.RegisterType((*QuerySubspacesResponse)(nil), "cosmos.params.v1beta1.QuerySubspacesResponse")
proto.RegisterType((*Subspace)(nil), "cosmos.params.v1beta1.Subspace")
}
func init() { proto.RegisterFile("cosmos/params/v1beta1/query.proto", fileDescriptor_2b32979c1792ccc4) }
var fileDescriptor_2b32979c1792ccc4 = []byte{
// 321 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x91, 0x31, 0x4b, 0x3b, 0x31,
0x14, 0xc0, 0x2f, 0xfd, 0xff, 0x5b, 0x34, 0x2e, 0x12, 0x15, 0xca, 0xa1, 0x57, 0x3d, 0x10, 0x54,
0x30, 0xa1, 0xd5, 0xd9, 0xa1, 0xee, 0xa2, 0x05, 0x17, 0xb7, 0x5c, 0x0d, 0x69, 0x69, 0x7b, 0x2f,
0xbd, 0x97, 0x13, 0xbb, 0x3a, 0x38, 0x17, 0xfc, 0x52, 0x1d, 0x0b, 0x2e, 0x4e, 0x22, 0xad, 0x1f,
0x44, 0x9a, 0xb4, 0x82, 0x58, 0xc5, 0x29, 0x2f, 0x2f, 0xbf, 0xf7, 0x7b, 0x79, 0x09, 0xdd, 0x6b,
0x02, 0xf6, 0x00, 0x85, 0x91, 0x99, 0xec, 0xa1, 0xb8, 0xab, 0x26, 0xca, 0xca, 0xaa, 0xe8, 0xe7,
0x2a, 0x1b, 0x70, 0x93, 0x81, 0x05, 0xb6, 0xe5, 0x11, 0xee, 0x11, 0x3e, 0x47, 0xc2, 0x4d, 0x0d,
0x1a, 0x1c, 0x21, 0x66, 0x91, 0x87, 0xc3, 0x6d, 0x0d, 0xa0, 0xbb, 0x4a, 0x48, 0xd3, 0x16, 0x32,
0x4d, 0xc1, 0x4a, 0xdb, 0x86, 0x14, 0xe7, 0xa7, 0xf1, 0xf2, 0x6e, 0x73, 0xb3, 0x63, 0xe2, 0x3a,
0x65, 0x57, 0xb3, 0xee, 0x97, 0x2e, 0xd9, 0x50, 0xfd, 0x5c, 0xa1, 0x65, 0x21, 0x5d, 0xc1, 0x3c,
0x41, 0x23, 0x9b, 0xaa, 0x4c, 0x76, 0xc9, 0xc1, 0x6a, 0xe3, 0x73, 0xcf, 0xd6, 0xe9, 0xbf, 0x8e,
0x1a, 0x94, 0x0b, 0x2e, 0x3d, 0x0b, 0xe3, 0x6b, 0xba, 0xf1, 0xc5, 0x81, 0x06, 0x52, 0x54, 0xec,
0x8c, 0x16, 0x5d, 0x2b, 0x67, 0x58, 0xab, 0xc5, 0x7c, 0xe9, 0x64, 0xdc, 0x55, 0x9d, 0xb7, 0x64,
0xaa, 0x55, 0xfd, 0xff, 0xe8, 0xb5, 0x12, 0x34, 0x7c, 0x59, 0x6d, 0x48, 0x68, 0xd1, 0x79, 0xd9,
0x23, 0xa1, 0x25, 0x2f, 0x67, 0x87, 0x3f, 0x58, 0xbe, 0x0f, 0x11, 0x1e, 0xfd, 0x05, 0xf5, 0x77,
0x8d, 0xf7, 0x1f, 0x9e, 0xdf, 0x9f, 0x0a, 0x15, 0xb6, 0x23, 0x7e, 0x7b, 0xb3, 0xfa, 0xc5, 0x68,
0x12, 0x91, 0xf1, 0x24, 0x22, 0x6f, 0x93, 0x88, 0x0c, 0xa7, 0x51, 0x30, 0x9e, 0x46, 0xc1, 0xcb,
0x34, 0x0a, 0x6e, 0x4e, 0x75, 0xdb, 0xb6, 0xf2, 0x84, 0x37, 0xa1, 0xb7, 0x50, 0xf8, 0xe5, 0x18,
0x6f, 0x3b, 0xe2, 0x7e, 0xe1, 0xb3, 0x03, 0xa3, 0x50, 0x98, 0x0c, 0x0c, 0xa0, 0xec, 0x26, 0x25,
0xf7, 0x09, 0x27, 0x1f, 0x01, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xd5, 0x67, 0xc7, 0x18, 0x02, 0x00,
0x00,
// 415 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x52, 0x4d, 0x8b, 0xd3, 0x40,
0x18, 0xce, 0xa4, 0x1f, 0x34, 0xd3, 0x8b, 0x8c, 0x56, 0x43, 0xd0, 0x34, 0x0e, 0x08, 0x51, 0x6c,
0x86, 0x56, 0x4f, 0x82, 0x1e, 0xea, 0x5d, 0x34, 0x22, 0x82, 0xb7, 0x49, 0x1d, 0xd2, 0xd2, 0x36,
0x33, 0xcd, 0x24, 0x62, 0xae, 0x1e, 0x3c, 0x2f, 0xbb, 0xbf, 0x61, 0xff, 0x4b, 0x8f, 0x85, 0xbd,
0xec, 0x69, 0x59, 0xda, 0xfd, 0x21, 0x4b, 0x27, 0x49, 0x97, 0xed, 0xb6, 0xa5, 0xa7, 0xbc, 0x79,
0xe7, 0xf9, 0x9a, 0x27, 0x81, 0x2f, 0x07, 0x5c, 0x4e, 0xb9, 0x24, 0x82, 0xc6, 0x74, 0x2a, 0xc9,
0x9f, 0x6e, 0xc0, 0x12, 0xda, 0x25, 0xb3, 0x94, 0xc5, 0x99, 0x27, 0x62, 0x9e, 0x70, 0xd4, 0xca,
0x21, 0x5e, 0x0e, 0xf1, 0x0a, 0x88, 0xf5, 0x24, 0xe4, 0x21, 0x57, 0x08, 0xb2, 0x9e, 0x72, 0xb0,
0xf5, 0x3c, 0xe4, 0x3c, 0x9c, 0x30, 0x42, 0xc5, 0x88, 0xd0, 0x28, 0xe2, 0x09, 0x4d, 0x46, 0x3c,
0x92, 0xc5, 0x29, 0xde, 0xed, 0x56, 0x28, 0x2b, 0x0c, 0xee, 0x43, 0xf4, 0x6d, 0xed, 0xfe, 0x55,
0x2d, 0x7d, 0x36, 0x4b, 0x99, 0x4c, 0x90, 0x05, 0x1b, 0x32, 0x0d, 0xa4, 0xa0, 0x03, 0x66, 0x02,
0x07, 0xb8, 0x86, 0xbf, 0x79, 0x47, 0x8f, 0x60, 0x65, 0xcc, 0x32, 0x53, 0x57, 0xeb, 0xf5, 0x88,
0x7f, 0xc0, 0xc7, 0xf7, 0x34, 0xa4, 0xe0, 0x91, 0x64, 0xe8, 0x13, 0xac, 0x29, 0x2b, 0xa5, 0xd0,
0xec, 0x61, 0x6f, 0xe7, 0xcd, 0x3c, 0xc5, 0xfa, 0x3c, 0xa4, 0x51, 0xc8, 0xfa, 0xd5, 0xf9, 0x55,
0x5b, 0xf3, 0x73, 0x1a, 0x7e, 0x06, 0x5b, 0x4a, 0xf6, 0x7b, 0xe1, 0x5c, 0xa6, 0xc3, 0x3f, 0xe1,
0xd3, 0xed, 0x83, 0xc2, 0xf2, 0x23, 0x34, 0xca, 0x9c, 0xd2, 0x04, 0x4e, 0xc5, 0x6d, 0xf6, 0xda,
0x7b, 0x6c, 0x4b, 0xb2, 0x7f, 0xc7, 0xc0, 0x1f, 0x60, 0xa3, 0x5c, 0x1f, 0xac, 0x00, 0xc1, 0xea,
0x98, 0x65, 0xd2, 0xd4, 0x9d, 0x8a, 0x6b, 0xf8, 0x6a, 0xee, 0x9d, 0xeb, 0xb0, 0xa6, 0x52, 0xa1,
0xff, 0x00, 0xd6, 0xf3, 0x2a, 0xd0, 0xeb, 0x3d, 0xe6, 0x0f, 0x2b, 0xb7, 0xde, 0x1c, 0x03, 0xcd,
0xaf, 0x89, 0x5f, 0xfd, 0xbb, 0xb8, 0x39, 0xd3, 0xdb, 0xe8, 0x05, 0x39, 0xf4, 0x85, 0xd1, 0x29,
0x80, 0xc6, 0xa6, 0x23, 0xf4, 0xf6, 0x90, 0xc1, 0x76, 0xc7, 0x56, 0xe7, 0x48, 0x74, 0x91, 0xc8,
0x55, 0x89, 0x30, 0x72, 0xf6, 0x24, 0xda, 0x74, 0xdc, 0xff, 0x32, 0x5f, 0xda, 0x60, 0xb1, 0xb4,
0xc1, 0xf5, 0xd2, 0x06, 0x27, 0x2b, 0x5b, 0x5b, 0xac, 0x6c, 0xed, 0x72, 0x65, 0x6b, 0xbf, 0xde,
0x87, 0xa3, 0x64, 0x98, 0x06, 0xde, 0x80, 0x4f, 0x4b, 0x95, 0xfc, 0xd1, 0x91, 0xbf, 0xc7, 0xe4,
0x6f, 0x29, 0x99, 0x64, 0x82, 0x49, 0x22, 0x62, 0x2e, 0xb8, 0xa4, 0x93, 0xa0, 0xae, 0xfe, 0xe3,
0x77, 0xb7, 0x01, 0x00, 0x00, 0xff, 0xff, 0x69, 0xa9, 0xbc, 0x11, 0x5b, 0x03, 0x00, 0x00,
}
// Reference imports to suppress errors if they are not otherwise used.
@ -177,6 +323,8 @@ type QueryClient interface {
// Params queries a specific parameter of a module, given its subspace and
// key.
Params(ctx context.Context, in *QueryParamsRequest, opts ...grpc.CallOption) (*QueryParamsResponse, error)
// Subspaces queries for all registered subspaces and all keys for a subspace.
Subspaces(ctx context.Context, in *QuerySubspacesRequest, opts ...grpc.CallOption) (*QuerySubspacesResponse, error)
}
type queryClient struct {
@ -196,11 +344,22 @@ func (c *queryClient) Params(ctx context.Context, in *QueryParamsRequest, opts .
return out, nil
}
func (c *queryClient) Subspaces(ctx context.Context, in *QuerySubspacesRequest, opts ...grpc.CallOption) (*QuerySubspacesResponse, error) {
out := new(QuerySubspacesResponse)
err := c.cc.Invoke(ctx, "/cosmos.params.v1beta1.Query/Subspaces", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// QueryServer is the server API for Query service.
type QueryServer interface {
// Params queries a specific parameter of a module, given its subspace and
// key.
Params(context.Context, *QueryParamsRequest) (*QueryParamsResponse, error)
// Subspaces queries for all registered subspaces and all keys for a subspace.
Subspaces(context.Context, *QuerySubspacesRequest) (*QuerySubspacesResponse, error)
}
// UnimplementedQueryServer can be embedded to have forward compatible implementations.
@ -210,6 +369,9 @@ type UnimplementedQueryServer struct {
func (*UnimplementedQueryServer) Params(ctx context.Context, req *QueryParamsRequest) (*QueryParamsResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method Params not implemented")
}
func (*UnimplementedQueryServer) Subspaces(ctx context.Context, req *QuerySubspacesRequest) (*QuerySubspacesResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method Subspaces not implemented")
}
func RegisterQueryServer(s grpc1.Server, srv QueryServer) {
s.RegisterService(&_Query_serviceDesc, srv)
@ -233,6 +395,24 @@ func _Query_Params_Handler(srv interface{}, ctx context.Context, dec func(interf
return interceptor(ctx, in, info, handler)
}
func _Query_Subspaces_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(QuerySubspacesRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(QueryServer).Subspaces(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/cosmos.params.v1beta1.Query/Subspaces",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(QueryServer).Subspaces(ctx, req.(*QuerySubspacesRequest))
}
return interceptor(ctx, in, info, handler)
}
var _Query_serviceDesc = grpc.ServiceDesc{
ServiceName: "cosmos.params.v1beta1.Query",
HandlerType: (*QueryServer)(nil),
@ -241,6 +421,10 @@ var _Query_serviceDesc = grpc.ServiceDesc{
MethodName: "Params",
Handler: _Query_Params_Handler,
},
{
MethodName: "Subspaces",
Handler: _Query_Subspaces_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "cosmos/params/v1beta1/query.proto",
@ -316,6 +500,105 @@ func (m *QueryParamsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
return len(dAtA) - i, nil
}
func (m *QuerySubspacesRequest) 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 *QuerySubspacesRequest) MarshalTo(dAtA []byte) (int, error) {
size := m.Size()
return m.MarshalToSizedBuffer(dAtA[:size])
}
func (m *QuerySubspacesRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) {
i := len(dAtA)
_ = i
var l int
_ = l
return len(dAtA) - i, nil
}
func (m *QuerySubspacesResponse) 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 *QuerySubspacesResponse) MarshalTo(dAtA []byte) (int, error) {
size := m.Size()
return m.MarshalToSizedBuffer(dAtA[:size])
}
func (m *QuerySubspacesResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
i := len(dAtA)
_ = i
var l int
_ = l
if len(m.Subspaces) > 0 {
for iNdEx := len(m.Subspaces) - 1; iNdEx >= 0; iNdEx-- {
{
size, err := m.Subspaces[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 (m *Subspace) 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 *Subspace) MarshalTo(dAtA []byte) (int, error) {
size := m.Size()
return m.MarshalToSizedBuffer(dAtA[:size])
}
func (m *Subspace) MarshalToSizedBuffer(dAtA []byte) (int, error) {
i := len(dAtA)
_ = i
var l int
_ = l
if len(m.Keys) > 0 {
for iNdEx := len(m.Keys) - 1; iNdEx >= 0; iNdEx-- {
i -= len(m.Keys[iNdEx])
copy(dAtA[i:], m.Keys[iNdEx])
i = encodeVarintQuery(dAtA, i, uint64(len(m.Keys[iNdEx])))
i--
dAtA[i] = 0x12
}
}
if len(m.Subspace) > 0 {
i -= len(m.Subspace)
copy(dAtA[i:], m.Subspace)
i = encodeVarintQuery(dAtA, i, uint64(len(m.Subspace)))
i--
dAtA[i] = 0xa
}
return len(dAtA) - i, nil
}
func encodeVarintQuery(dAtA []byte, offset int, v uint64) int {
offset -= sovQuery(v)
base := offset
@ -355,6 +638,49 @@ func (m *QueryParamsResponse) Size() (n int) {
return n
}
func (m *QuerySubspacesRequest) Size() (n int) {
if m == nil {
return 0
}
var l int
_ = l
return n
}
func (m *QuerySubspacesResponse) Size() (n int) {
if m == nil {
return 0
}
var l int
_ = l
if len(m.Subspaces) > 0 {
for _, e := range m.Subspaces {
l = e.Size()
n += 1 + l + sovQuery(uint64(l))
}
}
return n
}
func (m *Subspace) Size() (n int) {
if m == nil {
return 0
}
var l int
_ = l
l = len(m.Subspace)
if l > 0 {
n += 1 + l + sovQuery(uint64(l))
}
if len(m.Keys) > 0 {
for _, s := range m.Keys {
l = len(s)
n += 1 + l + sovQuery(uint64(l))
}
}
return n
}
func sovQuery(x uint64) (n int) {
return (math_bits.Len64(x|1) + 6) / 7
}
@ -558,6 +884,254 @@ func (m *QueryParamsResponse) Unmarshal(dAtA []byte) error {
}
return nil
}
func (m *QuerySubspacesRequest) 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: QuerySubspacesRequest: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: QuerySubspacesRequest: 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 *QuerySubspacesResponse) 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: QuerySubspacesResponse: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: QuerySubspacesResponse: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Subspaces", 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.Subspaces = append(m.Subspaces, &Subspace{})
if err := m.Subspaces[len(m.Subspaces)-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 (m *Subspace) 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: Subspace: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: Subspace: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Subspace", 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.Subspace = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
case 2:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Keys", 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.Keys = append(m.Keys, 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 skipQuery(dAtA []byte) (n int, err error) {
l := len(dAtA)
iNdEx := 0

View File

@ -67,6 +67,24 @@ func local_request_Query_Params_0(ctx context.Context, marshaler runtime.Marshal
}
func request_Query_Subspaces_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq QuerySubspacesRequest
var metadata runtime.ServerMetadata
msg, err := client.Subspaces(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return msg, metadata, err
}
func local_request_Query_Subspaces_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq QuerySubspacesRequest
var metadata runtime.ServerMetadata
msg, err := server.Subspaces(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.
@ -93,6 +111,26 @@ func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, serv
})
mux.Handle("GET", pattern_Query_Subspaces_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_Subspaces_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_Subspaces_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
return nil
}
@ -154,13 +192,37 @@ func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, clie
})
mux.Handle("GET", pattern_Query_Subspaces_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_Subspaces_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_Subspaces_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
return nil
}
var (
pattern_Query_Params_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 1}, []string{"cosmos", "params", "v1beta1"}, "", runtime.AssumeColonVerbOpt(false)))
pattern_Query_Subspaces_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"cosmos", "params", "v1beta1", "subspaces"}, "", runtime.AssumeColonVerbOpt(false)))
)
var (
forward_Query_Params_0 = runtime.ForwardResponseMessage
forward_Query_Subspaces_0 = runtime.ForwardResponseMessage
)

View File

@ -127,6 +127,22 @@ func (s Subspace) GetIfExists(ctx sdk.Context, key []byte, ptr interface{}) {
}
}
// IterateKeys iterates over all the keys in the subspace and executes the
// provided callback. If the callback returns true for a given key, iteration
// will halt.
func (s Subspace) IterateKeys(ctx sdk.Context, cb func(key []byte) bool) {
store := s.kvStore(ctx)
iter := sdk.KVStorePrefixIterator(store, nil)
defer iter.Close()
for ; iter.Valid(); iter.Next() {
if cb(iter.Key()) {
break
}
}
}
// GetRaw queries for the raw values bytes for a parameter by key.
func (s Subspace) GetRaw(ctx sdk.Context, key []byte) []byte {
store := s.kvStore(ctx)

View File

@ -1,6 +1,7 @@
package types_test
import (
"bytes"
"fmt"
"testing"
"time"
@ -92,6 +93,41 @@ func (suite *SubspaceTestSuite) TestGetRaw() {
})
}
func (suite *SubspaceTestSuite) TestIterateKeys() {
suite.Require().NotPanics(func() {
suite.ss.Set(suite.ctx, keyUnbondingTime, time.Second)
})
suite.Require().NotPanics(func() {
suite.ss.Set(suite.ctx, keyMaxValidators, uint16(50))
})
suite.Require().NotPanics(func() {
suite.ss.Set(suite.ctx, keyBondDenom, "stake")
})
var keys [][]byte
suite.ss.IterateKeys(suite.ctx, func(key []byte) bool {
keys = append(keys, key)
return false
})
suite.Require().Len(keys, 3)
suite.Require().Contains(keys, keyUnbondingTime)
suite.Require().Contains(keys, keyMaxValidators)
suite.Require().Contains(keys, keyBondDenom)
var keys2 [][]byte
suite.ss.IterateKeys(suite.ctx, func(key []byte) bool {
if bytes.Equal(key, keyUnbondingTime) {
return true
}
keys2 = append(keys2, key)
return false
})
suite.Require().Len(keys2, 2)
suite.Require().Contains(keys2, keyMaxValidators)
suite.Require().Contains(keys2, keyBondDenom)
}
func (suite *SubspaceTestSuite) TestHas() {
t := time.Hour * 48