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

Add & update IBC queriers for relayer use #5901

Merged
merged 10 commits into from
Apr 2, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions x/ibc/03-connection/client/utils/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import (

// QueryAllConnections returns all the connections. It _does not_ return
// any merkle proof.
func QueryAllConnections(cliCtx context.CLIContext, page, limit int) ([]types.ConnectionEnd, int64, error) {
func QueryAllConnections(cliCtx context.CLIContext, page, limit int) ([]types.IdentifiedConnectionEnd, int64, error) {
params := types.NewQueryAllConnectionsParams(page, limit)
bz, err := cliCtx.Codec.MarshalJSON(params)
if err != nil {
Expand All @@ -30,7 +30,7 @@ func QueryAllConnections(cliCtx context.CLIContext, page, limit int) ([]types.Co
return nil, 0, err
}

var connections []types.ConnectionEnd
var connections []types.IdentifiedConnectionEnd
err = cliCtx.Codec.UnmarshalJSON(res, &connections)
if err != nil {
return nil, 0, fmt.Errorf("failed to unmarshal connections: %w", err)
Expand Down
9 changes: 5 additions & 4 deletions x/ibc/03-connection/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,24 +87,25 @@ func (k Keeper) SetClientConnectionPaths(ctx sdk.Context, clientID string, paths
// IterateConnections provides an iterator over all ConnectionEnd objects.
// For each ConnectionEnd, cb will be called. If the cb returns true, the
// iterator will close and stop.
func (k Keeper) IterateConnections(ctx sdk.Context, cb func(types.ConnectionEnd) bool) {
func (k Keeper) IterateConnections(ctx sdk.Context, cb func(types.IdentifiedConnectionEnd) bool) {
store := ctx.KVStore(k.storeKey)
iterator := sdk.KVStorePrefixIterator(store, ibctypes.KeyConnectionPrefix)

defer iterator.Close()
for ; iterator.Valid(); iterator.Next() {
var connection types.ConnectionEnd
k.cdc.MustUnmarshalBinaryLengthPrefixed(iterator.Value(), &connection)
identifier := string(iterator.Key()[len(ibctypes.KeyConnectionPrefix)+1:])

if cb(connection) {
if cb(types.IdentifiedConnectionEnd{connection, identifier}) {
cwgoes marked this conversation as resolved.
Show resolved Hide resolved
break
}
}
}

// GetAllConnections returns all stored ConnectionEnd objects.
func (k Keeper) GetAllConnections(ctx sdk.Context) (connections []types.ConnectionEnd) {
k.IterateConnections(ctx, func(connection types.ConnectionEnd) bool {
func (k Keeper) GetAllConnections(ctx sdk.Context) (connections []types.IdentifiedConnectionEnd) {
k.IterateConnections(ctx, func(connection types.IdentifiedConnectionEnd) bool {
connections = append(connections, connection)
return false
})
Expand Down
12 changes: 8 additions & 4 deletions x/ibc/03-connection/keeper/keeper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,11 +111,15 @@ func (suite KeeperTestSuite) TestGetAllConnections() {
conn2 := types.NewConnectionEnd(exported.INIT, testClientIDB, counterparty1, types.GetCompatibleVersions())
conn3 := types.NewConnectionEnd(exported.UNINITIALIZED, testClientID3, counterparty2, types.GetCompatibleVersions())

expConnections := []types.ConnectionEnd{conn1, conn2, conn3}
expConnections := []types.IdentifiedConnectionEnd{
{Connection: conn1, Identifier: testConnectionIDA},
{Connection: conn2, Identifier: testConnectionIDB},
{Connection: conn3, Identifier: testConnectionID3},
}

suite.chainA.App.IBCKeeper.ConnectionKeeper.SetConnection(suite.chainA.GetContext(), testConnectionIDA, expConnections[0])
suite.chainA.App.IBCKeeper.ConnectionKeeper.SetConnection(suite.chainA.GetContext(), testConnectionIDB, expConnections[1])
suite.chainA.App.IBCKeeper.ConnectionKeeper.SetConnection(suite.chainA.GetContext(), testConnectionID3, expConnections[2])
suite.chainA.App.IBCKeeper.ConnectionKeeper.SetConnection(suite.chainA.GetContext(), testConnectionIDA, conn1)
suite.chainA.App.IBCKeeper.ConnectionKeeper.SetConnection(suite.chainA.GetContext(), testConnectionIDB, conn2)
suite.chainA.App.IBCKeeper.ConnectionKeeper.SetConnection(suite.chainA.GetContext(), testConnectionID3, conn3)

connections := suite.chainA.App.IBCKeeper.ConnectionKeeper.GetAllConnections(suite.chainA.GetContext())
suite.Require().Len(connections, len(expConnections))
Expand Down
2 changes: 1 addition & 1 deletion x/ibc/03-connection/keeper/querier.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ func QuerierConnections(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]byt

start, end := client.Paginate(len(connections), params.Page, params.Limit, 100)
if start < 0 || end < 0 {
connections = []types.ConnectionEnd{}
connections = []types.IdentifiedConnectionEnd{}
} else {
connections = connections[start:end]
}
Expand Down
10 changes: 8 additions & 2 deletions x/ibc/03-connection/types/querier.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,16 @@ const (
QueryClientConnections = "client_connections"
)

// IdentifiedConnectionEnd defines the union of a connection end & an identifier.
type IdentifiedConnectionEnd struct {
Connection ConnectionEnd `json:"connection_end" yaml:"connection_end"`
Identifier string `json:"identifier" yaml:"identifier"`
}

// ConnectionResponse defines the client query response for a connection which
// also includes a proof and the height from which the proof was retrieved.
type ConnectionResponse struct {
Connection ConnectionEnd `json:"connection" yaml:"connection"`
Connection IdentifiedConnectionEnd `json:"connection" yaml:"connection"`
Proof commitmenttypes.MerkleProof `json:"proof,omitempty" yaml:"proof,omitempty"`
ProofPath commitmenttypes.MerklePath `json:"proof_path,omitempty" yaml:"proof_path,omitempty"`
ProofHeight uint64 `json:"proof_height,omitempty" yaml:"proof_height,omitempty"`
Expand All @@ -29,7 +35,7 @@ func NewConnectionResponse(
connectionID string, connection ConnectionEnd, proof *merkle.Proof, height int64,
) ConnectionResponse {
return ConnectionResponse{
Connection: connection,
Connection: IdentifiedConnectionEnd{connection, connectionID},
Proof: commitmenttypes.MerkleProof{Proof: proof},
ProofPath: commitmenttypes.NewMerklePath(strings.Split(ibctypes.ConnectionPath(connectionID), "/")),
ProofHeight: uint64(height),
Expand Down
14 changes: 8 additions & 6 deletions x/ibc/04-channel/alias.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,20 @@ import (
)

const (
SubModuleName = types.SubModuleName
StoreKey = types.StoreKey
RouterKey = types.RouterKey
QuerierRoute = types.QuerierRoute
QueryAllChannels = types.QueryAllChannels
QueryChannel = types.QueryChannel
SubModuleName = types.SubModuleName
StoreKey = types.StoreKey
RouterKey = types.RouterKey
QuerierRoute = types.QuerierRoute
QueryAllChannels = types.QueryAllChannels
QueryConnectionChannels = types.QueryConnectionChannels
QueryChannel = types.QueryChannel
)

var (
// functions aliases
NewKeeper = keeper.NewKeeper
QuerierChannels = keeper.QuerierChannels
QuerierConnectionChannels = keeper.QuerierConnectionChannels
NewChannel = types.NewChannel
NewCounterparty = types.NewCounterparty
RegisterCodec = types.RegisterCodec
Expand Down
4 changes: 2 additions & 2 deletions x/ibc/04-channel/client/utils/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ func QueryPacket(
return types.PacketResponse{}, err
}

destPortID := channelRes.Channel.Counterparty.PortID
destChannelID := channelRes.Channel.Counterparty.ChannelID
destPortID := channelRes.Channel.Channel.Counterparty.PortID
destChannelID := channelRes.Channel.Channel.Counterparty.ChannelID

packet := types.NewPacket(
res.Value,
Expand Down
9 changes: 5 additions & 4 deletions x/ibc/04-channel/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -151,24 +151,25 @@ func (k Keeper) GetPacketAcknowledgement(ctx sdk.Context, portID, channelID stri
// IterateChannels provides an iterator over all Channel objects. For each
// Channel, cb will be called. If the cb returns true, the iterator will close
// and stop.
func (k Keeper) IterateChannels(ctx sdk.Context, cb func(types.Channel) bool) {
func (k Keeper) IterateChannels(ctx sdk.Context, cb func(types.IdentifiedChannel) bool) {
store := ctx.KVStore(k.storeKey)
iterator := sdk.KVStorePrefixIterator(store, ibctypes.GetChannelPortsKeysPrefix(ibctypes.KeyChannelPrefix))

defer iterator.Close()
for ; iterator.Valid(); iterator.Next() {
var channel types.Channel
k.cdc.MustUnmarshalBinaryLengthPrefixed(iterator.Value(), &channel)
portID, channelID := ibctypes.MustParseChannelPath(string(iterator.Key()))

if cb(channel) {
if cb(types.IdentifiedChannel{Channel: channel, PortIdentifier: portID, ChannelIdentifier: channelID}) {
break
}
}
}

// GetAllChannels returns all stored Channel objects.
func (k Keeper) GetAllChannels(ctx sdk.Context) (channels []types.Channel) {
k.IterateChannels(ctx, func(channel types.Channel) bool {
func (k Keeper) GetAllChannels(ctx sdk.Context) (channels []types.IdentifiedChannel) {
k.IterateChannels(ctx, func(channel types.IdentifiedChannel) bool {
channels = append(channels, channel)
return false
})
Expand Down
12 changes: 8 additions & 4 deletions x/ibc/04-channel/keeper/keeper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,12 +121,16 @@ func (suite KeeperTestSuite) TestGetAllChannels() {
Version: testChannelVersion,
}

expChannels := []types.Channel{channel1, channel2, channel3}
expChannels := []types.IdentifiedChannel{
{Channel: channel1, PortIdentifier: testPort1, ChannelIdentifier: testChannel1},
{Channel: channel2, PortIdentifier: testPort2, ChannelIdentifier: testChannel2},
{Channel: channel3, PortIdentifier: testPort3, ChannelIdentifier: testChannel3},
}

ctx := suite.chainB.GetContext()
suite.chainB.App.IBCKeeper.ChannelKeeper.SetChannel(ctx, testPort1, testChannel1, expChannels[0])
suite.chainB.App.IBCKeeper.ChannelKeeper.SetChannel(ctx, testPort2, testChannel2, expChannels[1])
suite.chainB.App.IBCKeeper.ChannelKeeper.SetChannel(ctx, testPort3, testChannel3, expChannels[2])
suite.chainB.App.IBCKeeper.ChannelKeeper.SetChannel(ctx, testPort1, testChannel1, channel1)
suite.chainB.App.IBCKeeper.ChannelKeeper.SetChannel(ctx, testPort2, testChannel2, channel2)
suite.chainB.App.IBCKeeper.ChannelKeeper.SetChannel(ctx, testPort3, testChannel3, channel3)

channels := suite.chainB.App.IBCKeeper.ChannelKeeper.GetAllChannels(ctx)
suite.Require().Len(channels, len(expChannels))
Expand Down
34 changes: 33 additions & 1 deletion x/ibc/04-channel/keeper/querier.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ func QuerierChannels(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]byte,

start, end := client.Paginate(len(channels), params.Page, params.Limit, 100)
if start < 0 || end < 0 {
channels = []types.Channel{}
channels = []types.IdentifiedChannel{}
} else {
channels = channels[start:end]
}
Expand All @@ -34,3 +34,35 @@ func QuerierChannels(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]byte,

return res, nil
}

// QuerierConnectionChannels defines the sdk.Querier to query all the channels for a connection.
func QuerierConnectionChannels(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]byte, error) {
var params types.QueryConnectionChannelsParams

if err := k.cdc.UnmarshalJSON(req.Data, &params); err != nil {
return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error())
}

channels := k.GetAllChannels(ctx)

connectionChannels := []types.IdentifiedChannel{}
for _, channel := range channels {
if channel.Channel.ConnectionHops[0] == params.Connection {
connectionChannels = append(connectionChannels, channel)
}
}

start, end := client.Paginate(len(connectionChannels), params.Page, params.Limit, 100)
if start < 0 || end < 0 {
connectionChannels = []types.IdentifiedChannel{}
} else {
connectionChannels = channels[start:end]
}

res, err := codec.MarshalJSONIndent(k.cdc, connectionChannels)
if err != nil {
return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error())
}

return res, nil
}
32 changes: 28 additions & 4 deletions x/ibc/04-channel/types/querier.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,21 @@ import (

// query routes supported by the IBC channel Querier
const (
QueryAllChannels = "channels"
QueryChannel = "channel"
QueryAllChannels = "channels"
QueryChannel = "channel"
QueryConnectionChannels = "connection-channels"
)

type IdentifiedChannel struct {
Channel Channel `json:"channel_end" yaml:"channel_end"`
PortIdentifier string `json:"port_identifier" yaml:"port_identifier"`
ChannelIdentifier string `json:"channel_identifier" yaml:"channel_identifier"`
}

// ChannelResponse defines the client query response for a channel which also
// includes a proof,its path and the height from which the proof was retrieved.
type ChannelResponse struct {
Channel Channel `json:"channel" yaml:"channel"`
Channel IdentifiedChannel `json:"channel" yaml:"channel"`
Proof commitmenttypes.MerkleProof `json:"proof,omitempty" yaml:"proof,omitempty"`
ProofPath commitmenttypes.MerklePath `json:"proof_path,omitempty" yaml:"proof_path,omitempty"`
ProofHeight uint64 `json:"proof_height,omitempty" yaml:"proof_height,omitempty"`
Expand All @@ -29,7 +36,7 @@ func NewChannelResponse(
portID, channelID string, channel Channel, proof *merkle.Proof, height int64,
) ChannelResponse {
return ChannelResponse{
Channel: channel,
Channel: IdentifiedChannel{Channel: channel, PortIdentifier: portID, ChannelIdentifier: channelID},
Proof: commitmenttypes.MerkleProof{Proof: proof},
ProofPath: commitmenttypes.NewMerklePath(strings.Split(ibctypes.ChannelPath(portID, channelID), "/")),
ProofHeight: uint64(height),
Expand All @@ -51,6 +58,23 @@ func NewQueryAllChannelsParams(page, limit int) QueryAllChannelsParams {
}
}

// QueryConnectionChannelsParams defines the parameters necessary for querying
// for all channels associated with a given connection.
type QueryConnectionChannelsParams struct {
Connection string `json:"connection" yaml:"connection"`
Page int `json:"page" yaml:"page"`
Limit int `json:"limit" yaml:"limit"`
}

// NewQueryConnectionChannelsParams creates a new QueryConnectionChannelsParams instance.
func NewQueryConnectionChannelsParams(connection string, page, limit int) QueryConnectionChannelsParams {
return QueryConnectionChannelsParams{
Connection: connection,
Page: page,
Limit: limit,
}
}

// PacketResponse defines the client query response for a packet which also
// includes a proof, its path and the height form which the proof was retrieved
type PacketResponse struct {
Expand Down
2 changes: 2 additions & 0 deletions x/ibc/keeper/querier.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ func NewQuerier(k Keeper) sdk.Querier {
switch path[1] {
case channel.QueryAllChannels:
res, err = channel.QuerierChannels(ctx, req, k.ChannelKeeper)
case channel.QueryConnectionChannels:
res, err = channel.QuerierConnectionChannels(ctx, req, k.ChannelKeeper)
default:
err = sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unknown IBC %s query endpoint", channel.SubModuleName)
}
Expand Down
6 changes: 6 additions & 0 deletions x/ibc/keeper/querier_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,12 @@ func (suite *KeeperTestSuite) TestNewQuerier() {
false,
"",
},
{
"channel - QuerierConnectionChannels",
[]string{channel.SubModuleName, channel.QueryConnectionChannels},
false,
"",
},
{
"channel - invalid query",
[]string{channel.SubModuleName, "foo"},
Expand Down
16 changes: 15 additions & 1 deletion x/ibc/types/keys.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package types

import "fmt"
import (
"fmt"
"strings"
)

const (
// ModuleName is the name of the IBC module
Expand Down Expand Up @@ -179,6 +182,17 @@ func channelPath(portID, channelID string) string {
return fmt.Sprintf("ports/%s/channels/%s", portID, channelID)
}

func MustParseChannelPath(path string) (string, string) {
split := strings.Split(path, "/")
if len(split) != 5 {
panic("cannot parse channel path")
}
if split[1] != "ports" || split[3] != "channels" {
panic("cannot parse channel path")
}
return split[2], split[4]
}

// ICS05
// The following paths are the keys to the store as defined in https://github.com/cosmos/ics/tree/master/spec/ics-005-port-allocation#store-paths

Expand Down