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

Deterministic connection and channel identifiers #7993

Merged
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
0462943
add generate identifier functions for connection and channel
colin-axner Nov 20, 2020
44174ec
update proto types and begin open init changes
colin-axner Nov 20, 2020
e01eb98
finish connection handshake chanes and some channel handshake changes
colin-axner Nov 20, 2020
2119731
finish channel handshake changes
colin-axner Nov 20, 2020
7a1c317
fix more tests
colin-axner Nov 20, 2020
38f3901
fix connection handshake tests
colin-axner Nov 20, 2020
f47d238
fix more tests
colin-axner Nov 20, 2020
9af89dc
fix build
colin-axner Nov 20, 2020
36b9c66
Merge branch 'master' into colin/7870-deterministic-channel-connectio…
colin-axner Nov 20, 2020
f953238
Merge branch 'master' into colin/7870-deterministic-channel-connectio…
colin-axner Nov 23, 2020
32a1afa
changes from self review
colin-axner Nov 23, 2020
005c47a
Merge branch 'colin/7870-deterministic-channel-connection-identifiers…
colin-axner Nov 23, 2020
d89548a
address @fedekunze review suggestions
colin-axner Nov 23, 2020
db991d7
update spec
colin-axner Nov 23, 2020
fb8f829
fix build
colin-axner Nov 23, 2020
1b6bebf
fix tests
colin-axner Nov 23, 2020
fa62c83
Update x/ibc/testing/chain.go
colin-axner Nov 23, 2020
2341f86
Merge branch 'master' into colin/7870-deterministic-channel-connectio…
colin-axner Nov 23, 2020
916b3f7
Update x/ibc/core/03-connection/types/msgs.go
colin-axner Nov 23, 2020
3da13bd
address @AdityaSripal comments
colin-axner Nov 23, 2020
6818209
Merge branch 'master' into colin/7870-deterministic-channel-connectio…
colin-axner Nov 23, 2020
e671648
reflect spec changes
colin-axner Nov 24, 2020
49d2cd7
Merge branch 'master' into colin/7870-deterministic-channel-connectio…
colin-axner Nov 24, 2020
736a139
address @AdityaSripal review suggestions
colin-axner Nov 24, 2020
ec8e1f2
Merge branch 'colin/7870-deterministic-channel-connection-identifiers…
colin-axner Nov 24, 2020
f8c2970
nit
colin-axner Nov 24, 2020
2e80297
add connection/channel identifier parsing and validation as per @Adit…
colin-axner Nov 24, 2020
cb850b9
Merge branch 'master' into colin/7870-deterministic-channel-connectio…
colin-axner Nov 24, 2020
6024dbb
Fix auth rest test
colin-axner Nov 24, 2020
e3948d2
Merge branch 'colin/7870-deterministic-channel-connection-identifiers…
colin-axner Nov 24, 2020
c3c8cd9
Merge branch 'master' into colin/7870-deterministic-channel-connectio…
colin-axner Nov 24, 2020
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
29 changes: 14 additions & 15 deletions proto/ibc/core/channel/v1/tx.proto
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,9 @@ message MsgChannelOpenInit {
option (gogoproto.equal) = false;
option (gogoproto.goproto_getters) = false;

string port_id = 1 [(gogoproto.moretags) = "yaml:\"port_id\""];
string channel_id = 2 [(gogoproto.moretags) = "yaml:\"channel_id\""];
Channel channel = 3 [(gogoproto.nullable) = false];
string signer = 4;
string port_id = 1 [(gogoproto.moretags) = "yaml:\"port_id\""];
Channel channel = 2 [(gogoproto.nullable) = false];
string signer = 3;
}

// MsgChannelOpenInitResponse defines the Msg/ChannelOpenInit response type.
Expand Down Expand Up @@ -147,9 +146,9 @@ message MsgRecvPacket {
option (gogoproto.equal) = false;
option (gogoproto.goproto_getters) = false;

Packet packet = 1 [(gogoproto.nullable) = false];
bytes proof_commitment = 2 [(gogoproto.moretags) = "yaml:\"proof_commitment\""];
ibc.core.client.v1.Height proof_height = 3
Packet packet = 1 [(gogoproto.nullable) = false];
bytes proof_commitment = 2 [(gogoproto.moretags) = "yaml:\"proof_commitment\""];
ibc.core.client.v1.Height proof_height = 3
[(gogoproto.moretags) = "yaml:\"proof_height\"", (gogoproto.nullable) = false];
string signer = 4;
}
Expand All @@ -162,9 +161,9 @@ message MsgTimeout {
option (gogoproto.equal) = false;
option (gogoproto.goproto_getters) = false;

Packet packet = 1 [(gogoproto.nullable) = false];
bytes proof_unreceived = 2 [(gogoproto.moretags) = "yaml:\"proof_unreceived\""];
ibc.core.client.v1.Height proof_height = 3
Packet packet = 1 [(gogoproto.nullable) = false];
bytes proof_unreceived = 2 [(gogoproto.moretags) = "yaml:\"proof_unreceived\""];
ibc.core.client.v1.Height proof_height = 3
[(gogoproto.moretags) = "yaml:\"proof_height\"", (gogoproto.nullable) = false];
uint64 next_sequence_recv = 4 [(gogoproto.moretags) = "yaml:\"next_sequence_recv\""];
string signer = 5;
Expand All @@ -178,10 +177,10 @@ message MsgTimeoutOnClose {
option (gogoproto.equal) = false;
option (gogoproto.goproto_getters) = false;

Packet packet = 1 [(gogoproto.nullable) = false];
bytes proof_unreceived = 2 [(gogoproto.moretags) = "yaml:\"proof_unreceived\""];
bytes proof_close = 3 [(gogoproto.moretags) = "yaml:\"proof_close\""];
ibc.core.client.v1.Height proof_height = 4
Packet packet = 1 [(gogoproto.nullable) = false];
bytes proof_unreceived = 2 [(gogoproto.moretags) = "yaml:\"proof_unreceived\""];
bytes proof_close = 3 [(gogoproto.moretags) = "yaml:\"proof_close\""];
ibc.core.client.v1.Height proof_height = 4
[(gogoproto.moretags) = "yaml:\"proof_height\"", (gogoproto.nullable) = false];
uint64 next_sequence_recv = 5 [(gogoproto.moretags) = "yaml:\"next_sequence_recv\""];
string signer = 6;
Expand All @@ -197,7 +196,7 @@ message MsgAcknowledgement {

Packet packet = 1 [(gogoproto.nullable) = false];
bytes acknowledgement = 2;
bytes proof_acked = 3 [(gogoproto.moretags) = "yaml:\"proof_acked\""];
bytes proof_acked = 3 [(gogoproto.moretags) = "yaml:\"proof_acked\""];
ibc.core.client.v1.Height proof_height = 4
[(gogoproto.moretags) = "yaml:\"proof_height\"", (gogoproto.nullable) = false];
string signer = 5;
Expand Down
9 changes: 4 additions & 5 deletions proto/ibc/core/connection/v1/tx.proto
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,10 @@ message MsgConnectionOpenInit {
option (gogoproto.equal) = false;
option (gogoproto.goproto_getters) = false;

string client_id = 1 [(gogoproto.moretags) = "yaml:\"client_id\""];
string connection_id = 2 [(gogoproto.moretags) = "yaml:\"connection_id\""];
Counterparty counterparty = 3 [(gogoproto.nullable) = false];
Version version = 4;
string signer = 5;
string client_id = 1 [(gogoproto.moretags) = "yaml:\"client_id\""];
Counterparty counterparty = 2 [(gogoproto.nullable) = false];
Version version = 3;
string signer = 4;
}

// MsgConnectionOpenInitResponse defines the Msg/ConnectionOpenInit response type.
Expand Down
10 changes: 5 additions & 5 deletions proto/ibc/lightclients/solomachine/v1/solomachine.proto
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,11 @@ message Header {
// Misbehaviour defines misbehaviour for a solo machine which consists
// of a sequence and two signatures over different messages at that sequence.
message Misbehaviour {
option (gogoproto.goproto_getters) = false;
string client_id = 1 [(gogoproto.moretags) = "yaml:\"client_id\""];
uint64 sequence = 2;
SignatureAndData signature_one = 3 [(gogoproto.moretags) = "yaml:\"signature_one\""];
SignatureAndData signature_two = 4 [(gogoproto.moretags) = "yaml:\"signature_two\""];
option (gogoproto.goproto_getters) = false;
string client_id = 1 [(gogoproto.moretags) = "yaml:\"client_id\""];
uint64 sequence = 2;
SignatureAndData signature_one = 3 [(gogoproto.moretags) = "yaml:\"signature_one\""];
SignatureAndData signature_two = 4 [(gogoproto.moretags) = "yaml:\"signature_two\""];
}

// SignatureAndData contains a signature and the data signed over to create that
Expand Down
2 changes: 1 addition & 1 deletion proto/ibc/lightclients/tendermint/v1/tendermint.proto
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ message ConsensusState {
// Misbehaviour is a wrapper over two conflicting Headers
// that implements Misbehaviour interface expected by ICS-02
message Misbehaviour {
option (gogoproto.goproto_getters) = false;
option (gogoproto.goproto_getters) = false;

string client_id = 1 [(gogoproto.moretags) = "yaml:\"client_id\""];
Header header_1 = 2 [(gogoproto.customname) = "Header1", (gogoproto.moretags) = "yaml:\"header_1\""];
Expand Down
17 changes: 8 additions & 9 deletions x/ibc/core/03-connection/client/cli/tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,29 +29,28 @@ const (
// chain A with a given counterparty chain B
func NewConnectionOpenInitCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "open-init [connection-id] [client-id] [counterparty-connection-id] [counterparty-client-id] [path/to/counterparty_prefix.json]",
Use: "open-init [client-id] [counterparty-connection-id] [counterparty-client-id] [path/to/counterparty_prefix.json]",
Short: "Initialize connection on chain A",
Long: `Initialize a connection on chain A with a given counterparty chain B.
- 'version-identifier' flag can be a single pre-selected version identifier to be used in the handshake.
- 'version-features' flag can be a list of features separated by commas to accompany the version identifier.`,
Example: fmt.Sprintf(
"%s tx %s %s open-init [connection-id] [client-id] [counterparty-connection-id] [counterparty-client-id] [path/to/counterparty_prefix.json] --version-identifier=\"1.0\" --version-features=\"ORDER_UNORDERED\"",
"%s tx %s %s open-init [client-id] [counterparty-connection-id] [counterparty-client-id] [path/to/counterparty_prefix.json] --version-identifier=\"1.0\" --version-features=\"ORDER_UNORDERED\"",
version.AppName, host.ModuleName, types.SubModuleName,
),
Args: cobra.ExactArgs(5),
Args: cobra.ExactArgs(4),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx := client.GetClientContextFromCmd(cmd)
clientCtx, err := client.ReadTxCommandFlags(clientCtx, cmd.Flags())
if err != nil {
return err
}

connectionID := args[0]
clientID := args[1]
counterpartyConnectionID := args[2]
counterpartyClientID := args[3]
clientID := args[0]
counterpartyConnectionID := args[1]
counterpartyClientID := args[2]

counterpartyPrefix, err := utils.ParsePrefix(clientCtx.LegacyAmino, args[4])
counterpartyPrefix, err := utils.ParsePrefix(clientCtx.LegacyAmino, args[3])
if err != nil {
return err
}
Expand All @@ -71,7 +70,7 @@ func NewConnectionOpenInitCmd() *cobra.Command {
}

msg := types.NewMsgConnectionOpenInit(
connectionID, clientID, counterpartyConnectionID, counterpartyClientID,
clientID, counterpartyConnectionID, counterpartyClientID,
counterpartyPrefix, version, clientCtx.GetFromAddress(),
)

Expand Down
23 changes: 10 additions & 13 deletions x/ibc/core/03-connection/keeper/handshake.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,36 +14,33 @@ import (
"github.com/cosmos/cosmos-sdk/x/ibc/core/exported"
)

// ConnOpenInit initialises a connection attempt on chain A.
// ConnOpenInit initialises a connection attempt on chain A. The generated connection identifier
// is returned.
//
// NOTE: Identifiers are checked on msg validation.
// NOTE: Msg validation verifies the supplied identifiers and ensures that the counterparty
// connection identifier is empty.
func (k Keeper) ConnOpenInit(
ctx sdk.Context,
connectionID, // identifier
clientID string,
counterparty types.Counterparty, // desiredCounterpartyConnectionIdentifier, counterpartyPrefix, counterpartyClientIdentifier
counterparty types.Counterparty, // counterpartyPrefix, counterpartyClientIdentifier
version *types.Version,
) error {
_, found := k.GetConnection(ctx, connectionID)
if found {
return sdkerrors.Wrap(types.ErrConnectionExists, connectionID)
}

) (string, error) {
versions := types.GetCompatibleVersions()
if version != nil {
if !types.IsSupportedVersion(version) {
return sdkerrors.Wrap(types.ErrInvalidVersion, "version is not supported")
return "", sdkerrors.Wrap(types.ErrInvalidVersion, "version is not supported")
}

versions = []exported.Version{version}
}

// connection defines chain A's ConnectionEnd
connectionID := k.GenerateConnectionIdentifier(ctx)
connection := types.NewConnectionEnd(types.INIT, clientID, counterparty, types.ExportedVersionsToProto(versions))
k.SetConnection(ctx, connectionID, connection)

if err := k.addConnectionToClient(ctx, clientID, connectionID); err != nil {
return err
return "", err
}

k.Logger(ctx).Info("connection state updated", "connection-id", connectionID, "previous-state", "NONE", "new-state", "INIT")
Expand All @@ -52,7 +49,7 @@ func (k Keeper) ConnOpenInit(
telemetry.IncrCounter(1, "ibc", "connection", "open-init")
}()

return nil
return connectionID, nil
}

// ConnOpenTry relays notice of a connection attempt on chain A to chain B (this
Expand Down
29 changes: 29 additions & 0 deletions x/ibc/core/03-connection/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,17 @@ func (k Keeper) GetCommitmentPrefix() exported.Prefix {
return commitmenttypes.NewMerklePrefix([]byte(k.storeKey.Name()))
}

// GenerateConnectionIdentifier returns the next connection identifier.
func (k Keeper) GenerateConnectionIdentifier(ctx sdk.Context) string {
nextConnSeq := k.GetNextConnectionSequence(ctx)
connectionID := fmt.Sprintf("%s%d", types.ConnectionPrefix, nextConnSeq)
Copy link
Collaborator

Choose a reason for hiding this comment

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

should we add a separator here to avoid collisions?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Collisions with what? The identifier is auto derived, not user inputted


nextConnSeq++
k.SetNextConnectionSequence(ctx, nextConnSeq)

return connectionID
}

// GetConnection returns a connection with a particular identifier
func (k Keeper) GetConnection(ctx sdk.Context, connectionID string) (types.ConnectionEnd, bool) {
store := ctx.KVStore(k.storeKey)
Expand Down Expand Up @@ -105,6 +116,24 @@ func (k Keeper) SetClientConnectionPaths(ctx sdk.Context, clientID string, paths
store.Set(host.ClientConnectionsKey(clientID), bz)
}

// GetNextConnectionSequence gets the next connection sequence from the store.
func (k Keeper) GetNextConnectionSequence(ctx sdk.Context) uint64 {
store := ctx.KVStore(k.storeKey)
bz := store.Get([]byte(types.KeyNextConnectionSequence))
if bz == nil {
panic("next connection sequence is nil")
Copy link
Collaborator

Choose a reason for hiding this comment

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

why not return 0, error?

Copy link
Contributor Author

@colin-axner colin-axner Nov 20, 2020

Choose a reason for hiding this comment

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

This means we didn't set it on init genesis. It is an assumption that the global counter is always set otherwise core IBC won't function properly. If it isn't set the chain should halt and fix the issue

}

return sdk.BigEndianToUint64(bz)
}

// SetNextConnectionSequence sets the next connection sequence to the store
func (k Keeper) SetNextConnectionSequence(ctx sdk.Context, sequence uint64) {
store := ctx.KVStore(k.storeKey)
bz := sdk.Uint64ToBigEndian(sequence)
store.Set([]byte(types.KeyNextConnectionSequence), bz)
}

// GetAllClientConnectionPaths returns all stored clients connection id paths. It
// will ignore the clients that haven't initialized a connection handshake since
// no paths are stored.
Expand Down
7 changes: 7 additions & 0 deletions x/ibc/core/03-connection/types/keys.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,11 @@ const (

// QuerierRoute is the querier route for IBC connections
QuerierRoute = SubModuleName

// KeyNextConnectionSequence is the key used to store the next connection sequence in
// the keeper.
KeyNextConnectionSequence = "nextConnectionSequence"

// ConnectionPrefix is the prefix used when creating a connection identifier
ConnectionPrefix = "connection"
)
10 changes: 5 additions & 5 deletions x/ibc/core/03-connection/types/msgs.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,12 @@ var _ sdk.Msg = &MsgConnectionOpenInit{}
// NewMsgConnectionOpenInit creates a new MsgConnectionOpenInit instance
//nolint:interfacer
func NewMsgConnectionOpenInit(
connectionID, clientID, counterpartyConnectionID,
clientID, counterpartyConnectionID,
counterpartyClientID string, counterpartyPrefix commitmenttypes.MerklePrefix,
version *Version, signer sdk.AccAddress,
) *MsgConnectionOpenInit {
counterparty := NewCounterparty(counterpartyClientID, counterpartyConnectionID, counterpartyPrefix)
return &MsgConnectionOpenInit{
ConnectionId: connectionID,
ClientId: clientID,
Counterparty: counterparty,
Version: version,
Expand All @@ -41,12 +40,13 @@ func (msg MsgConnectionOpenInit) Type() string {

// ValidateBasic implements sdk.Msg.
func (msg MsgConnectionOpenInit) ValidateBasic() error {
if err := host.ConnectionIdentifierValidator(msg.ConnectionId); err != nil {
return sdkerrors.Wrap(err, "invalid connection ID")
}
if err := host.ClientIdentifierValidator(msg.ClientId); err != nil {
return sdkerrors.Wrap(err, "invalid client ID")
}
if msg.Counterparty.ConnectionId != "" {
return sdkerrors.Wrap(ErrInvalidCounterparty, "counterparty connection identifier must be empty")
}

// NOTE: Version can be nil on MsgConnectionOpenInit
if msg.Version != nil {
if err := ValidateVersion(msg.Version); err != nil {
Expand Down
13 changes: 6 additions & 7 deletions x/ibc/core/04-channel/client/cli/tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@ const (
// NewChannelOpenInitCmd returns the command to create a MsgChannelOpenInit transaction
func NewChannelOpenInitCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "open-init [port-id] [channel-id] [counterparty-port-id] [counterparty-channel-id] [connection-hops]",
Use: "open-init [port-id] [counterparty-port-id] [counterparty-channel-id] [connection-hops]",
Short: "Creates and sends a ChannelOpenInit message",
Args: cobra.ExactArgs(5),
Args: cobra.ExactArgs(4),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx := client.GetClientContextFromCmd(cmd)
clientCtx, err := client.ReadTxCommandFlags(clientCtx, cmd.Flags())
Expand All @@ -35,15 +35,14 @@ func NewChannelOpenInitCmd() *cobra.Command {
}

portID := args[0]
channelID := args[1]
counterpartyPortID := args[2]
counterpartyChannelID := args[3]
hops := strings.Split(args[4], "/")
counterpartyPortID := args[1]
counterpartyChannelID := args[2]
hops := strings.Split(args[3], "/")
order := channelOrder(cmd.Flags())
version, _ := cmd.Flags().GetString(FlagIBCVersion)

msg := types.NewMsgChannelOpenInit(
portID, channelID, version, order, hops,
portID, version, order, hops,
counterpartyPortID, counterpartyChannelID, clientCtx.GetFromAddress(),
)
if err := msg.ValidateBasic(); err != nil {
Expand Down
2 changes: 1 addition & 1 deletion x/ibc/core/04-channel/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (
// HandleMsgChannelOpenInit defines the sdk.Handler for MsgChannelOpenInit
func HandleMsgChannelOpenInit(ctx sdk.Context, k keeper.Keeper, portCap *capabilitytypes.Capability, msg *types.MsgChannelOpenInit) (*sdk.Result, *capabilitytypes.Capability, error) {
capKey, err := k.ChanOpenInit(
ctx, msg.Channel.Ordering, msg.Channel.ConnectionHops, msg.PortId, msg.ChannelId,
ctx, msg.Channel.Ordering, msg.Channel.ConnectionHops, msg.PortId,
portCap, msg.Channel.Counterparty, msg.Channel.Version,
)
if err != nil {
Expand Down
24 changes: 24 additions & 0 deletions x/ibc/core/04-channel/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,12 @@ func (k Keeper) Logger(ctx sdk.Context) log.Logger {
return ctx.Logger().With("module", fmt.Sprintf("x/%s/%s", host.ModuleName, types.SubModuleName))
}

// GenerateChannelIdentifier returns the next channel identifier.
func (k Keeper) GenerateConnectionIdentifier(ctx sdk.Context) string {
nextChannelSeq := k.GetNextChannelSequence(ctx)
return fmt.Sprintf("%s%d", types.ChannelPrefix, nextChannelSeq)
}

// GetChannel returns a channel with a particular identifier binded to a specific port
func (k Keeper) GetChannel(ctx sdk.Context, portID, channelID string) (types.Channel, bool) {
store := ctx.KVStore(k.storeKey)
Expand All @@ -75,6 +81,24 @@ func (k Keeper) SetChannel(ctx sdk.Context, portID, channelID string, channel ty
store.Set(host.ChannelKey(portID, channelID), bz)
}

// GetNextChannelSequence gets the next channel sequence from the store.
func (k Keeper) GetNextChannelSequence(ctx sdk.Context) uint64 {
store := ctx.KVStore(k.storeKey)
bz := store.Get([]byte(types.KeyNextChannelSequence))
if bz == nil {
panic("next channel sequence is nil")
Copy link
Collaborator

Choose a reason for hiding this comment

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

ditto 0, error

}

return sdk.BigEndianToUint64(bz)
}

// SetNextChannelSequence sets the next channel sequence to the store
func (k Keeper) SetNextChannelSequence(ctx sdk.Context, sequence uint64) {
store := ctx.KVStore(k.storeKey)
bz := sdk.Uint64ToBigEndian(sequence)
store.Set([]byte(types.KeyNextChannelSequence), bz)
}

// GetNextSequenceSend gets a channel's next send sequence from the store
func (k Keeper) GetNextSequenceSend(ctx sdk.Context, portID, channelID string) (uint64, bool) {
store := ctx.KVStore(k.storeKey)
Expand Down
7 changes: 7 additions & 0 deletions x/ibc/core/04-channel/types/keys.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,11 @@ const (

// QuerierRoute is the querier route for IBC channels
QuerierRoute = SubModuleName

// KeyNextChannelSequence is the key used to store the next channel sequence in
// the keeper.
KeyNextChannelSequence = "nextChannelSequence"

// ChannelPrefix is the prefix used when creating a channel identifier
ChannelPrefix = "channel"
)
Loading