-
Notifications
You must be signed in to change notification settings - Fork 586
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: scalable version queries #384
Changes from 5 commits
3d0cdcc
81b0d8c
958ef81
43a63ee
349dbb5
8a7891e
20f466d
aea4a72
18d382c
d8f3673
5f0a231
52989a7
0c0fe69
485306f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
package cli | ||
|
||
import ( | ||
"github.com/spf13/cobra" | ||
|
||
"github.com/cosmos/cosmos-sdk/client" | ||
"github.com/cosmos/ibc-go/modules/core/05-port/types" | ||
) | ||
|
||
// GetQueryCmd returns the query commands for IBC channels | ||
colin-axner marked this conversation as resolved.
Show resolved
Hide resolved
|
||
func GetQueryCmd() *cobra.Command { | ||
queryCmd := &cobra.Command{ | ||
Use: types.SubModuleName, | ||
Short: "IBC port query subcommands", | ||
DisableFlagParsing: true, | ||
SuggestionsMinimumDistance: 2, | ||
RunE: client.ValidateCmd, | ||
} | ||
|
||
queryCmd.AddCommand( | ||
GetCmdQueryPort(), | ||
) | ||
|
||
return queryCmd | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
package cli | ||
|
||
import ( | ||
"fmt" | ||
|
||
"github.com/spf13/cobra" | ||
|
||
"github.com/cosmos/cosmos-sdk/client" | ||
"github.com/cosmos/cosmos-sdk/client/flags" | ||
"github.com/cosmos/cosmos-sdk/version" | ||
|
||
channeltypes "github.com/cosmos/ibc-go/modules/core/04-channel/types" | ||
"github.com/cosmos/ibc-go/modules/core/05-port/types" | ||
host "github.com/cosmos/ibc-go/modules/core/24-host" | ||
) | ||
|
||
// GetCmdQueryPorts defines the command to query a port | ||
colin-axner marked this conversation as resolved.
Show resolved
Hide resolved
|
||
func GetCmdQueryPort() *cobra.Command { | ||
cmd := &cobra.Command{ | ||
Use: "port [port-id] [counterparty-port-id] [counterparty-channel-id] [counterparty-version]", | ||
Short: "Query an IBC port", | ||
Long: "Query an IBC port by providing it's port ID and associated counterparty port and channel identifiers", | ||
Example: fmt.Sprintf("%s query %s %s port", version.AppName, host.ModuleName, types.SubModuleName), | ||
Args: cobra.ExactArgs(4), | ||
RunE: func(cmd *cobra.Command, args []string) error { | ||
clientCtx, err := client.GetClientQueryContext(cmd) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
queryClient := types.NewQueryClient(clientCtx) | ||
|
||
req := &types.QueryPortRequest{ | ||
PortId: args[0], | ||
Counterparty: &channeltypes.Counterparty{ | ||
PortId: args[1], | ||
ChannelId: args[2], | ||
}, | ||
CounterpartyVersion: args[3], | ||
} | ||
|
||
portRes, err := queryClient.Port(cmd.Context(), req) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
return clientCtx.PrintProto(portRes) | ||
}, | ||
} | ||
|
||
flags.AddQueryFlagsToCmd(cmd) | ||
|
||
return cmd | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
package keeper | ||
|
||
import ( | ||
"context" | ||
|
||
sdk "github.com/cosmos/cosmos-sdk/types" | ||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" | ||
"google.golang.org/grpc/codes" | ||
"google.golang.org/grpc/status" | ||
|
||
"github.com/cosmos/ibc-go/modules/core/05-port/types" | ||
host "github.com/cosmos/ibc-go/modules/core/24-host" | ||
) | ||
|
||
var _ types.QueryServer = (*Keeper)(nil) | ||
|
||
// Port implements the Query/Port gRPC method | ||
func (q Keeper) Port(c context.Context, req *types.QueryPortRequest) (*types.QueryPortResponse, error) { | ||
if req == nil { | ||
return nil, status.Error(codes.InvalidArgument, "empty request") | ||
} | ||
|
||
if err := validategRPCRequest(req.PortId); err != nil { | ||
return nil, err | ||
} | ||
|
||
ctx := sdk.UnwrapSDKContext(c) | ||
module, _, err := q.LookupModuleByPort(ctx, req.PortId) | ||
if err != nil { | ||
return nil, status.Errorf(codes.NotFound, sdkerrors.Wrap(err, "could not retrieve module from port-id").Error()) | ||
} | ||
|
||
ibcModule, found := q.Router.GetRoute(module) | ||
if !found { | ||
return nil, status.Errorf(codes.NotFound, sdkerrors.Wrapf(types.ErrInvalidRoute, "route not found to module: %s", module).Error()) | ||
} | ||
|
||
version, err := ibcModule.NegotiateAppVersion(ctx, req.PortId, *req.Counterparty, req.CounterpartyVersion) | ||
if err != nil { | ||
return nil, status.Errorf(codes.InvalidArgument, sdkerrors.Wrap(err, "version negotation failed").Error()) | ||
} | ||
|
||
return types.NewQueryPortResponse(req.PortId, version), nil | ||
} | ||
|
||
func validategRPCRequest(portID string) error { | ||
if err := host.PortIdentifierValidator(portID); err != nil { | ||
return status.Error(codes.InvalidArgument, err.Error()) | ||
} | ||
|
||
return nil | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
package port | ||
|
||
import ( | ||
"github.com/gogo/protobuf/grpc" | ||
"github.com/spf13/cobra" | ||
|
||
"github.com/cosmos/ibc-go/modules/core/05-port/types" | ||
"github.com/cosmos/ibc-go/modules/core/client/cli" | ||
) | ||
|
||
// Name returns the IBC port ICS name. | ||
func Name() string { | ||
return types.SubModuleName | ||
} | ||
|
||
// GetQueryCmd returns the root query command for IBC ports. | ||
func GetQueryCmd() *cobra.Command { | ||
return cli.GetQueryCmd() | ||
} | ||
|
||
// RegisterQueryService registers the gRPC query service for IBC ports. | ||
func RegisterQueryService(server grpc.Server, queryServer types.QueryServer) { | ||
types.RegisterQueryServer(server, queryServer) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -82,4 +82,11 @@ type IBCModule interface { | |
packet channeltypes.Packet, | ||
relayer sdk.AccAddress, | ||
) error | ||
|
||
NegotiateAppVersion( | ||
colin-axner marked this conversation as resolved.
Show resolved
Hide resolved
|
||
ctx sdk.Context, | ||
portID string, | ||
counterparty channeltypes.Counterparty, | ||
counterpartyVersion string, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Information not provided:
channel id cannot necessarily be known by OnChanOpenTry. Channel state shouldn't matter Should we include channel ordering and connection hops? We could always break API later to add it? I have no strong opinion except knowing the associated connection may be useful There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think there is no harm in adding it now. If I'm understanding you correctly, no current module requires these parameters for negotiating the counterparty version but adding them now will let future modules use as required? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Correct. To the best of my knowledge, interchain accounts is the first module introducing multiple valid versions. It's hard to know what version negotiation will look like for applications, but I agree probably best to be as flexible as possible |
||
) (version string, err error) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
package types | ||
|
||
// NewQueryPortResponse creates a new QueryPortResponse instance | ||
func NewQueryPortResponse(portID, version string) *QueryPortResponse { | ||
return &QueryPortResponse{ | ||
PortId: portID, | ||
Version: version, | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we can safely return an error here if there is a version mismatch.
One would imagine that a hypothetical
"ics20-2"
would involve breaking changes