Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: adding interchain account address query to controller submodule #2193

Merged
merged 12 commits into from Sep 8, 2022
Merged
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -98,6 +98,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
### Features

* (apps/27-interchain-accounts) [\#2147](https://github.com/cosmos/ibc-go/pull/2147) Adding a `SubmitTx` gRPC endpoint for the ICS27 Controller module which allows owners of interchain accounts to submit transactions. This replaces the previously existing need for authentication modules to implement this standard functionality.
* (apps/27-interchain-accounts) [\#2193](https://github.com/cosmos/ibc-go/pull/2193) Adding `InterchainAccount` gRPC query endpont to ICS27 `controller` submodule to allow users to retrieve registered interchain account addresses.

### Bug Fixes

Expand Down
58 changes: 58 additions & 0 deletions docs/client/swagger-ui/swagger.yaml
Expand Up @@ -365,6 +365,56 @@ paths:
format: byte
tags:
- Query
'/ibc/apps/interchain_accounts/controller/v1/owners/{owner}/connections/{connection_id}':
get:
summary: >-
InterchainAccount returns the interchain account address for a given
owner address on a given connection
operationId: InterchainAccount
responses:
'200':
description: A successful response.
schema:
type: object
properties:
address:
type: string
description: >-
QueryInterchainAccountResponse the response type for the
Query/InterchainAccount RPC method.
default:
description: An unexpected error response
schema:
type: object
properties:
error:
type: string
code:
type: integer
format: int32
message:
type: string
details:
type: array
items:
type: object
properties:
type_url:
type: string
value:
type: string
format: byte
parameters:
- name: owner
in: path
required: true
type: string
- name: connection_id
in: path
required: true
type: string
tags:
- Query
/ibc/apps/interchain_accounts/controller/v1/params:
get:
summary: Params queries all parameters of the ICA controller submodule.
Expand Down Expand Up @@ -13384,6 +13434,14 @@ definitions:
description: |-
Params defines the set of on-chain interchain accounts parameters.
The following parameters may be used to disable the controller submodule.
ibc.applications.interchain_accounts.controller.v1.QueryInterchainAccountResponse:
type: object
properties:
address:
type: string
description: >-
QueryInterchainAccountResponse the response type for the
Query/InterchainAccount RPC method.
ibc.applications.interchain_accounts.controller.v1.QueryParamsResponse:
type: object
properties:
Expand Down
34 changes: 34 additions & 0 deletions docs/ibc/proto-docs.md
Expand Up @@ -84,6 +84,8 @@
- [Params](#ibc.applications.interchain_accounts.controller.v1.Params)

- [ibc/applications/interchain_accounts/controller/v1/query.proto](#ibc/applications/interchain_accounts/controller/v1/query.proto)
- [QueryInterchainAccountRequest](#ibc.applications.interchain_accounts.controller.v1.QueryInterchainAccountRequest)
- [QueryInterchainAccountResponse](#ibc.applications.interchain_accounts.controller.v1.QueryInterchainAccountResponse)
- [QueryParamsRequest](#ibc.applications.interchain_accounts.controller.v1.QueryParamsRequest)
- [QueryParamsResponse](#ibc.applications.interchain_accounts.controller.v1.QueryParamsResponse)

Expand Down Expand Up @@ -1475,6 +1477,37 @@ The following parameters may be used to disable the controller submodule.



<a name="ibc.applications.interchain_accounts.controller.v1.QueryInterchainAccountRequest"></a>

### QueryInterchainAccountRequest
QueryInterchainAccountRequest is the request type for the Query/InterchainAccount RPC method.


| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `owner` | [string](#string) | | |
| `connection_id` | [string](#string) | | |






<a name="ibc.applications.interchain_accounts.controller.v1.QueryInterchainAccountResponse"></a>

### QueryInterchainAccountResponse
QueryInterchainAccountResponse the response type for the Query/InterchainAccount RPC method.


| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `address` | [string](#string) | | |






<a name="ibc.applications.interchain_accounts.controller.v1.QueryParamsRequest"></a>

### QueryParamsRequest
Expand Down Expand Up @@ -1513,6 +1546,7 @@ Query provides defines the gRPC querier service.

| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint |
| ----------- | ------------ | ------------- | ------------| ------- | -------- |
| `InterchainAccount` | [QueryInterchainAccountRequest](#ibc.applications.interchain_accounts.controller.v1.QueryInterchainAccountRequest) | [QueryInterchainAccountResponse](#ibc.applications.interchain_accounts.controller.v1.QueryInterchainAccountResponse) | InterchainAccount returns the interchain account address for a given owner address on a given connection | GET|/ibc/apps/interchain_accounts/controller/v1/owners/{owner}/connections/{connection_id}|
| `Params` | [QueryParamsRequest](#ibc.applications.interchain_accounts.controller.v1.QueryParamsRequest) | [QueryParamsResponse](#ibc.applications.interchain_accounts.controller.v1.QueryParamsResponse) | Params queries all parameters of the ICA controller submodule. | GET|/ibc/apps/interchain_accounts/controller/v1/params|

<!-- end services -->
Expand Down
Expand Up @@ -14,6 +14,7 @@ func GetQueryCmd() *cobra.Command {
}

queryCmd.AddCommand(
GetCmdQueryInterchainAccount(),
GetCmdParams(),
)

Expand Down
Expand Up @@ -11,6 +11,40 @@ import (
"github.com/cosmos/ibc-go/v5/modules/apps/27-interchain-accounts/controller/types"
)

// GetCmdQueryInterchainAccount returns the command handler for the controller submodule parameter querying.
func GetCmdQueryInterchainAccount() *cobra.Command {
cmd := &cobra.Command{
Use: "interchain-account [owner] [connection-id]",
Short: "Query the interchain account address for a given owner on a particular connection",
Long: "Query the controller submodule for the interchain account address for a given owner on a particular connection",
Args: cobra.ExactArgs(2),
Example: fmt.Sprintf("%s query interchain-accounts controller interchain-account connection-0 cosmos1layxcsmyye0dc0har9sdfzwckaz8sjwlfsj8zs", version.AppName),
damiannolan marked this conversation as resolved.
Show resolved Hide resolved
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientQueryContext(cmd)
if err != nil {
return err
}

queryClient := types.NewQueryClient(clientCtx)
req := &types.QueryInterchainAccountRequest{
Owner: args[0],
ConnectionId: args[1],
}

res, err := queryClient.InterchainAccount(cmd.Context(), req)
if err != nil {
return err
}

return clientCtx.PrintProto(res)
},
}

flags.AddQueryFlagsToCmd(cmd)

return cmd
}

// GetCmdParams returns the command handler for the controller submodule parameter querying.
func GetCmdParams() *cobra.Command {
cmd := &cobra.Command{
Expand Down
Expand Up @@ -4,16 +4,41 @@ import (
"context"

sdk "github.com/cosmos/cosmos-sdk/types"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"

"github.com/cosmos/ibc-go/v5/modules/apps/27-interchain-accounts/controller/types"
icatypes "github.com/cosmos/ibc-go/v5/modules/apps/27-interchain-accounts/types"
)

var _ types.QueryServer = Keeper{}

// InterchainAccount implements the Query/InterchainAccount gRPC method
func (k Keeper) InterchainAccount(goCtx context.Context, req *types.QueryInterchainAccountRequest) (*types.QueryInterchainAccountResponse, error) {
if req == nil {
return nil, status.Error(codes.InvalidArgument, "empty request")
}

portID, err := icatypes.NewControllerPortID(req.Owner)
if err != nil {
return nil, status.Errorf(codes.InvalidArgument, "failed to generate portID from owner address: %s", err)
}

ctx := sdk.UnwrapSDKContext(goCtx)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for readability, I kinda prefer this to be the first line, but I do get it technically is more efficient to do it later

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah I mostly agree with you tbh, but its kind of inconsistent across a lot of our grpc queries, maybe we can align them all in another PR.

addr, found := k.GetInterchainAccountAddress(ctx, req.ConnectionId, portID)
if !found {
return nil, status.Errorf(codes.NotFound, "failed to retrieve account address for %s on connection %s", portID, req.ConnectionId)
}

return &types.QueryInterchainAccountResponse{
Address: addr,
}, nil
}

// Params implements the Query/Params gRPC method
func (q Keeper) Params(c context.Context, _ *types.QueryParamsRequest) (*types.QueryParamsResponse, error) {
func (k Keeper) Params(c context.Context, _ *types.QueryParamsRequest) (*types.QueryParamsResponse, error) {
ctx := sdk.UnwrapSDKContext(c)
params := q.GetParams(ctx)
params := k.GetParams(ctx)

return &types.QueryParamsResponse{
Params: &params,
Expand Down
Expand Up @@ -4,8 +4,77 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"

"github.com/cosmos/ibc-go/v5/modules/apps/27-interchain-accounts/controller/types"
icatypes "github.com/cosmos/ibc-go/v5/modules/apps/27-interchain-accounts/types"
ibctesting "github.com/cosmos/ibc-go/v5/testing"
)

func (suite *KeeperTestSuite) TestQueryInterchainAccount() {
var req *types.QueryInterchainAccountRequest

testCases := []struct {
name string
malleate func()
expPass bool
}{
{
"success",
func() {},
true,
},
{
"empty request",
func() {
req = nil
},
false,
},
{
"empty owner address",
func() {
req.Owner = ""
},
false,
},
{
"invalid connection, account address not found",
func() {
req.ConnectionId = "invalid-connection-id"
},
false,
},
}

for _, tc := range testCases {
suite.Run(tc.name, func() {
suite.SetupTest()

path := NewICAPath(suite.chainA, suite.chainB)
suite.coordinator.SetupConnections(path)

err := SetupICAPath(path, ibctesting.TestAccAddress)
suite.Require().NoError(err)

req = &types.QueryInterchainAccountRequest{
ConnectionId: ibctesting.FirstConnectionID,
Owner: ibctesting.TestAccAddress,
}

tc.malleate()

res, err := suite.chainA.GetSimApp().ICAControllerKeeper.InterchainAccount(sdk.WrapSDKContext(suite.chainA.GetContext()), req)

if tc.expPass {
expAddress := icatypes.GenerateAddress(suite.chainA.GetSimApp().AccountKeeper.GetModuleAddress(icatypes.ModuleName), path.EndpointB.ConnectionID, path.EndpointA.ChannelConfig.PortID)

suite.Require().NoError(err)
suite.Require().Equal(expAddress.String(), res.Address)
} else {
suite.Require().Error(err)
}
})
}
}

func (suite *KeeperTestSuite) TestQueryParams() {
ctx := sdk.WrapSDKContext(suite.chainA.GetContext())
expParams := types.DefaultParams()
Expand Down