-
Notifications
You must be signed in to change notification settings - Fork 647
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
refactor: move ica connection identifiers from port to version metadata bytestring #700
Changes from 14 commits
e13b08c
a5e9947
a79ab75
f14d4dd
b8b0cbb
d5380ee
873d8cd
07a506d
dd95566
264b307
777ab3b
1e5bf8a
a3d1660
661502d
d02efed
52863e2
9ec698c
2ce783e
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 |
---|---|---|
|
@@ -15,8 +15,8 @@ import ( | |
// call 04-channel 'ChanOpenInit'. An error is returned if the port identifier is | ||
// already in use. Gaining access to interchain accounts whose channels have closed | ||
// cannot be done with this function. A regular MsgChanOpenInit must be used. | ||
func (k Keeper) InitInterchainAccount(ctx sdk.Context, connectionID, counterpartyConnectionID, owner string) error { | ||
portID, err := icatypes.GeneratePortID(owner, connectionID, counterpartyConnectionID) | ||
func (k Keeper) InitInterchainAccount(ctx sdk.Context, connectionID, owner string) error { | ||
portID, err := icatypes.NewControllerPortID(owner) | ||
if err != nil { | ||
return err | ||
} | ||
|
@@ -30,7 +30,18 @@ func (k Keeper) InitInterchainAccount(ctx sdk.Context, connectionID, counterpart | |
return sdkerrors.Wrap(err, "unable to bind to newly generated portID") | ||
} | ||
|
||
msg := channeltypes.NewMsgChannelOpenInit(portID, icatypes.VersionPrefix, channeltypes.ORDERED, []string{connectionID}, icatypes.PortID, icatypes.ModuleName) | ||
connectionEnd, err := k.channelKeeper.GetConnection(ctx, connectionID) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
metadata := icatypes.NewMetadata(icatypes.Version, connectionID, connectionEnd.GetCounterparty().GetConnectionID(), "") | ||
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. Okay, this is the new JSON metadata in the version field. I get it and like the design |
||
bz, err := icatypes.ModuleCdc.MarshalJSON(&metadata) | ||
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. nit: in this case I think it's more readable to name 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. Done |
||
if err != nil { | ||
return err | ||
} | ||
|
||
msg := channeltypes.NewMsgChannelOpenInit(portID, string(bz), channeltypes.ORDERED, []string{connectionID}, icatypes.PortID, icatypes.ModuleName) | ||
handler := k.msgRouter.Handler(msg) | ||
|
||
res, err := handler(ctx, msg) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,8 @@ | ||
package keeper | ||
|
||
import ( | ||
"strings" | ||
|
||
sdk "github.com/cosmos/cosmos-sdk/types" | ||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" | ||
capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types" | ||
|
@@ -32,26 +34,25 @@ func (k Keeper) OnChanOpenInit( | |
return sdkerrors.Wrapf(channeltypes.ErrInvalidChannelOrdering, "expected %s channel, got %s", channeltypes.ORDERED, order) | ||
} | ||
|
||
connSequence, err := icatypes.ParseControllerConnSequence(portID) | ||
if err != nil { | ||
return sdkerrors.Wrapf(err, "expected format %s, got %s", icatypes.ControllerPortFormat, portID) | ||
if !strings.HasPrefix(portID, icatypes.PortPrefix) { | ||
return sdkerrors.Wrapf(icatypes.ErrInvalidControllerPort, "expected %s{owner-account-address}, got %s", icatypes.PortPrefix, portID) | ||
} | ||
|
||
counterpartyConnSequence, err := icatypes.ParseHostConnSequence(portID) | ||
if err != nil { | ||
return sdkerrors.Wrapf(err, "expected format %s, got %s", icatypes.ControllerPortFormat, portID) | ||
if counterparty.PortId != icatypes.PortID { | ||
return sdkerrors.Wrapf(icatypes.ErrInvalidHostPort, "expected %s, got %s", icatypes.PortID, counterparty.PortId) | ||
} | ||
|
||
if err := k.validateControllerPortParams(ctx, connectionHops, connSequence, counterpartyConnSequence); err != nil { | ||
return sdkerrors.Wrapf(err, "failed to validate controller port %s", portID) | ||
var metadata icatypes.Metadata | ||
if err := icatypes.ModuleCdc.UnmarshalJSON([]byte(version), &metadata); err != nil { | ||
return sdkerrors.Wrapf(icatypes.ErrUnknownDataType, "cannot unmarshal ICS-27 interchain accounts metadata") | ||
} | ||
|
||
if counterparty.PortId != icatypes.PortID { | ||
return sdkerrors.Wrapf(porttypes.ErrInvalidPort, "expected %s, got %s", icatypes.PortID, counterparty.PortId) | ||
if err := k.validateConnectionParams(ctx, connectionHops, metadata.ControllerConnectionId, metadata.HostConnectionId); err != nil { | ||
return err | ||
} | ||
|
||
if version != icatypes.VersionPrefix { | ||
return sdkerrors.Wrapf(icatypes.ErrInvalidVersion, "expected %s, got %s", icatypes.VersionPrefix, version) | ||
if metadata.Version != icatypes.Version { | ||
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. Do we want to allow relayers to pass in empty string for version here? Or is this a future improvement? ref: https://github.com/cosmos/ibc/pull/629/files cc: @colin-axner This can also be implemented in a separate PR 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. Am I missing something here? We should probably be adding a defensive check to 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.
As far as I know, this is handled by core IBC already. You can't open a channel on a port that is not bound already. 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. You're right, it would be handled by core here in the case where a port is not bound 👍 |
||
return sdkerrors.Wrapf(icatypes.ErrInvalidVersion, "expected %s, got %s", icatypes.Version, metadata.Version) | ||
} | ||
|
||
activeChannelID, found := k.GetActiveChannelID(ctx, portID) | ||
|
@@ -71,21 +72,28 @@ func (k Keeper) OnChanOpenAck( | |
counterpartyVersion string, | ||
) error { | ||
if portID == icatypes.PortID { | ||
return sdkerrors.Wrapf(porttypes.ErrInvalidPort, "portID cannot be host chain port ID: %s", icatypes.PortID) | ||
return sdkerrors.Wrapf(icatypes.ErrInvalidControllerPort, "portID cannot be host chain port ID: %s", icatypes.PortID) | ||
} | ||
|
||
if err := icatypes.ValidateVersion(counterpartyVersion); err != nil { | ||
return sdkerrors.Wrap(err, "counterparty version validation failed") | ||
if !strings.HasPrefix(portID, icatypes.PortPrefix) { | ||
return sdkerrors.Wrapf(icatypes.ErrInvalidControllerPort, "expected %s{owner-account-address}, got %s", icatypes.PortPrefix, portID) | ||
} | ||
|
||
k.SetActiveChannelID(ctx, portID, channelID) | ||
var metadata icatypes.Metadata | ||
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. Would there be value in adding a 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 thought about this myself when I was implementing it, but I came to the conclusion that it wouldn't be so reusable as we need to carry out metadata validation in I've added 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 we still need to validate connection sequences here? It is possible the host chain chooses a bad metadata, followup issue 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. Sure, I can address this in a followup PR, with the moving of I assume retrieving the channel from state using channelKeeper, and passing along it's 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. Figured it made more sense to move this to a |
||
if err := icatypes.ModuleCdc.UnmarshalJSON([]byte(counterpartyVersion), &metadata); err != nil { | ||
return sdkerrors.Wrapf(icatypes.ErrUnknownDataType, "cannot unmarshal ICS-27 interchain accounts metadata") | ||
} | ||
|
||
accAddr, err := icatypes.ParseAddressFromVersion(counterpartyVersion) | ||
if err != nil { | ||
return sdkerrors.Wrapf(err, "expected format <app-version%saccount-address>, got %s", icatypes.Delimiter, counterpartyVersion) | ||
if err := icatypes.ValidateAccountAddress(metadata.Address); err != nil { | ||
return err | ||
} | ||
|
||
k.SetInterchainAccountAddress(ctx, portID, accAddr) | ||
if metadata.Version != icatypes.Version { | ||
return sdkerrors.Wrapf(icatypes.ErrInvalidVersion, "expected %s, got %s", icatypes.Version, metadata.Version) | ||
} | ||
|
||
k.SetActiveChannelID(ctx, portID, channelID) | ||
k.SetInterchainAccountAddress(ctx, portID, metadata.Address) | ||
|
||
return nil | ||
} | ||
|
@@ -102,31 +110,20 @@ func (k Keeper) OnChanCloseConfirm( | |
return nil | ||
} | ||
|
||
// validateControllerPortParams asserts the provided connection sequence and counterparty connection sequence | ||
// match that of the associated connection stored in state | ||
func (k Keeper) validateControllerPortParams(ctx sdk.Context, connectionHops []string, connectionSeq, counterpartyConnectionSeq uint64) error { | ||
// validateConnectionParams asserts the provided controller and host connection identifiers match that of the associated connection stored in state | ||
func (k Keeper) validateConnectionParams(ctx sdk.Context, connectionHops []string, controllerConnectionID, hostConnectionID string) error { | ||
damiannolan marked this conversation as resolved.
Show resolved
Hide resolved
|
||
connectionID := connectionHops[0] | ||
connection, err := k.channelKeeper.GetConnection(ctx, connectionID) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
connSeq, err := connectiontypes.ParseConnectionSequence(connectionID) | ||
if err != nil { | ||
return sdkerrors.Wrapf(err, "failed to parse connection sequence %s", connectionID) | ||
} | ||
|
||
counterpartyConnSeq, err := connectiontypes.ParseConnectionSequence(connection.GetCounterparty().GetConnectionID()) | ||
if err != nil { | ||
return sdkerrors.Wrapf(err, "failed to parse counterparty connection sequence %s", connection.GetCounterparty().GetConnectionID()) | ||
} | ||
|
||
if connSeq != connectionSeq { | ||
return sdkerrors.Wrapf(connectiontypes.ErrInvalidConnection, "sequence mismatch, expected %d, got %d", connSeq, connectionSeq) | ||
if controllerConnectionID != connectionID { | ||
return sdkerrors.Wrapf(connectiontypes.ErrInvalidConnection, "expected %s, got %s", connectionID, controllerConnectionID) | ||
} | ||
|
||
if counterpartyConnSeq != counterpartyConnectionSeq { | ||
return sdkerrors.Wrapf(connectiontypes.ErrInvalidConnection, "counterparty sequence mismatch, expected %d, got %d", counterpartyConnSeq, counterpartyConnectionSeq) | ||
if hostConnectionID != connection.GetCounterparty().GetConnectionID() { | ||
return sdkerrors.Wrapf(connectiontypes.ErrInvalidConnection, "expected %s, got %s", connection.GetCounterparty().GetConnectionID(), hostConnectionID) | ||
} | ||
|
||
return nil | ||
|
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.
Removed
counterpartyConnectionID
as it can be retrieved using the channelKeeper below. This reduces the burden on developers implementing their own authentication modulesThere 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.
Nice change. We need to update the spec should we change this @AdityaSripal @crodriguezvega
Likewise one of us should update the ICA repo + hub teams PR (the CLI commands take two connections etc)
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.
We also need to update the spec to explain the json-encoded format of the version string, right?