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

Implement OnChanUpgradeAck on Controller Chain for interchain-accounts #5160

Merged
Show file tree
Hide file tree
Changes from 43 commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
7372125
chore: adding controller implementation for OnChanUpgradeInit
chatton Nov 20, 2023
4427f1d
chore: happy path test passing
chatton Nov 20, 2023
978a7a2
chore: adding fail case
chatton Nov 20, 2023
925392f
chore: adding additional test cases
chatton Nov 21, 2023
fa5e349
chore: fix linting
chatton Nov 21, 2023
a49ce39
wip: working on implementation
chatton Nov 21, 2023
32dba02
chore: improving errors
chatton Nov 21, 2023
fa00f5c
Merge branch 'cian/issue#4512-implement-upgrade-callbacks-for-interch…
chatton Nov 21, 2023
c38be7c
chore: adding implementation for OnChanUpgradeTry
chatton Nov 21, 2023
4c74e08
test: adding happy path test case
chatton Nov 21, 2023
e22da0d
chore: refactor tests to call keeper fn directly
chatton Nov 21, 2023
292529e
chore: refactor to use test keeper function directly
chatton Nov 21, 2023
37eb4db
Merge branch 'cian/issue#4512-implement-upgrade-callbacks-for-interch…
chatton Nov 21, 2023
eb76314
chore: add check for enabled controller module
chatton Nov 21, 2023
15797db
chore: fix linter
chatton Nov 21, 2023
0d0e904
chore: adding host enabled check
chatton Nov 21, 2023
b40e160
Merge branch 'cian/issue#4512-implement-upgrade-callbacks-for-interch…
chatton Nov 21, 2023
fce51f5
wip: ack impl
chatton Nov 21, 2023
236f2d9
chore: call into middleware if provided
chatton Nov 21, 2023
75d31de
Merge branch 'cian/issue#4512-implement-upgrade-callbacks-for-interch…
chatton Nov 21, 2023
2656baa
chore: adding OnChanUpgradeAck implementation
chatton Nov 21, 2023
c0c43d7
chore: adding more test cases for OnChanUpgradeAck
chatton Nov 22, 2023
8420da9
Merge branch '04-channel-upgrades' into cian/issue#5142-implement-onc…
charleenfei Dec 7, 2023
50ec448
fix merge conflicts, update usage of getAppData
charleenfei Dec 7, 2023
e40e93b
rm unnecessary channel getter
charleenfei Dec 7, 2023
951f6a2
update test
charleenfei Dec 7, 2023
598650c
rm unnnecessary fields
charleenfei Dec 7, 2023
77694ed
Merge branch '04-channel-upgrades' into cian/issue#5145-implement-onc…
charleenfei Dec 7, 2023
d2df36f
Merge branch 'cian/issue#5142-implement-onchanupgradetry-on-host-chai…
charleenfei Dec 7, 2023
93c674e
update test
charleenfei Dec 7, 2023
b25eede
Merge branch '04-channel-upgrades' into cian/issue#5142-implement-onc…
charleenfei Dec 8, 2023
e154286
Merge branch '04-channel-upgrades' into cian/issue#5145-implement-onc…
charleenfei Dec 8, 2023
1e4723b
Merge branch '04-channel-upgrades' into cian/issue#5142-implement-onc…
charleenfei Dec 11, 2023
02774a2
refactor
charleenfei Dec 11, 2023
f5f5b37
Merge branch 'cian/issue#5142-implement-onchanupgradetry-on-host-chai…
charleenfei Dec 11, 2023
ec55099
Merge branch '04-channel-upgrades' into cian/issue#5145-implement-onc…
charleenfei Dec 11, 2023
6a32173
Merge branch 'cian/issue#5145-implement-onchanupgradeack-on-controlle…
charleenfei Dec 11, 2023
f988930
update validate metadata function
charleenfei Dec 11, 2023
a4ae803
refactor validate function
charleenfei Dec 11, 2023
2116cc6
separate validate functions
charleenfei Dec 11, 2023
a4ebc97
test
charleenfei Dec 11, 2023
f2ce3a5
Merge branch '04-channel-upgrades' into cian/issue#5145-implement-onc…
charleenfei Dec 11, 2023
a0c6ac4
Merge branch '04-channel-upgrades' into cian/issue#5145-implement-onc…
charleenfei Dec 12, 2023
82d876a
typo
charleenfei Dec 12, 2023
b91617b
Merge branch '04-channel-upgrades' into cian/issue#5145-implement-onc…
charleenfei Dec 12, 2023
05f7685
update for cbs routing
charleenfei Dec 12, 2023
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
19 changes: 18 additions & 1 deletion modules/apps/27-interchain-accounts/controller/ibc_middleware.go
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,24 @@ func (IBCMiddleware) OnChanUpgradeTry(ctx sdk.Context, portID, channelID string,
}

// OnChanUpgradeAck implements the IBCModule interface
func (IBCMiddleware) OnChanUpgradeAck(ctx sdk.Context, portID, channelID, counterpartyVersion string) error {
func (im IBCMiddleware) OnChanUpgradeAck(ctx sdk.Context, portID, channelID, counterpartyVersion string) error {
if !im.keeper.GetParams(ctx).ControllerEnabled {
return types.ErrControllerSubModuleDisabled
}

if err := im.keeper.OnChanUpgradeAck(ctx, portID, channelID, counterpartyVersion); err != nil {
return err
}

connectionID, err := im.keeper.GetConnectionID(ctx, portID, channelID)
if err != nil {
return err
}

if im.app != nil && im.keeper.IsMiddlewareEnabled(ctx, portID, connectionID) {
return im.app.OnChanUpgradeAck(ctx, portID, channelID, counterpartyVersion)
}

return nil
}

Expand Down
42 changes: 42 additions & 0 deletions modules/apps/27-interchain-accounts/controller/keeper/handshake.go
Original file line number Diff line number Diff line change
Expand Up @@ -173,3 +173,45 @@ func (k Keeper) OnChanUpgradeInit(ctx sdk.Context, portID, channelID string, con

return version, nil
}

// OnChanUpgradeAck implements the ack setup of the channel upgrade handshake.
func (k Keeper) OnChanUpgradeAck(ctx sdk.Context, portID, channelID, counterpartyVersion string) error {
if strings.TrimSpace(counterpartyVersion) == "" {
return errorsmod.Wrap(channeltypes.ErrInvalidChannelVersion, "counterparty version cannot be empty")
}

metadata, err := icatypes.MetadataFromVersion(counterpartyVersion)
if err != nil {
return err
}

currentMetadata, err := k.getAppMetadata(ctx, portID, channelID)
if err != nil {
return err
}

// the interchain account address on the host chain
// must remain the same after the upgrade.
if currentMetadata.Address != metadata.Address {
return errorsmod.Wrap(icatypes.ErrInvalidAccountAddress, "address cannot be changed")
}

if currentMetadata.ControllerConnectionId != metadata.ControllerConnectionId {
return errorsmod.Wrap(connectiontypes.ErrInvalidConnectionIdentifier, "proposed controller connection ID must not change")
}

if currentMetadata.HostConnectionId != metadata.HostConnectionId {
return errorsmod.Wrap(connectiontypes.ErrInvalidConnectionIdentifier, "proposed host connection ID must not change")
}

channel, found := k.channelKeeper.GetChannel(ctx, portID, channelID)
if !found {
return errorsmod.Wrapf(channeltypes.ErrChannelNotFound, "failed to retrieve channel %s on port %s", channelID, portID)
}

if err := icatypes.ValidateControllerMetadata(ctx, k.channelKeeper, channel.ConnectionHops, metadata); err != nil {
return err
}

return nil
}
Original file line number Diff line number Diff line change
Expand Up @@ -577,3 +577,147 @@ func (suite *KeeperTestSuite) TestOnChanUpgradeInit() {
})
}
}

func (suite *KeeperTestSuite) TestOnChanUpgradeAck() {
const (
invalidVersion = "invalid-version"
)

var (
path *ibctesting.Path
metadata icatypes.Metadata
counterpartyVersion string
)

// updateMetadata is a helper function which modifies the metadata stored in the channel version
// and marshals it into a string to passed to OnChanUpgradeAck as the counterpartyVersion string.
charleenfei marked this conversation as resolved.
Show resolved Hide resolved
updateMetadata := func(modificationFn func(*icatypes.Metadata)) {
metadata, err := icatypes.MetadataFromVersion(path.EndpointA.ChannelConfig.ProposedUpgrade.Fields.Version)
suite.Require().NoError(err)
modificationFn(&metadata)
counterpartyVersion = string(icatypes.ModuleCdc.MustMarshalJSON(&metadata))
}

testCases := []struct {
name string
malleate func()
expError error
}{
{
"success",
func() {},
nil,
},
{
name: "failure: empty counterparty version",
malleate: func() {
counterpartyVersion = ""
},
expError: channeltypes.ErrInvalidChannelVersion,
},
{
name: "failure: invalid counterparty version",
malleate: func() {
counterpartyVersion = invalidVersion
},
expError: icatypes.ErrUnknownDataType,
},
{
name: "failure: cannot decode self version string",
malleate: func() {
channel := path.EndpointA.GetChannel()
channel.Version = invalidVersion
path.EndpointA.SetChannel(channel)
},
expError: icatypes.ErrUnknownDataType,
},
{
name: "failure: invalid tx type",
malleate: func() {
updateMetadata(func(metadata *icatypes.Metadata) {
metadata.TxType = "invalid-tx-type"
})
},
expError: icatypes.ErrUnknownDataType,
},
{
name: "failure: interchain account address has changed",
malleate: func() {
updateMetadata(func(metadata *icatypes.Metadata) {
metadata.Address = "different-address"
})
},
expError: icatypes.ErrInvalidAccountAddress,
},
{
name: "failure: controller connection ID has changed",
malleate: func() {
updateMetadata(func(metadata *icatypes.Metadata) {
metadata.ControllerConnectionId = "different-connection-id"
})
},
expError: connectiontypes.ErrInvalidConnectionIdentifier,
},
{
name: "failure: host connection ID has changed",
malleate: func() {
updateMetadata(func(metadata *icatypes.Metadata) {
metadata.HostConnectionId = "different-host-id"
})
},
expError: connectiontypes.ErrInvalidConnectionIdentifier,
},
}

for _, tc := range testCases {
tc := tc

suite.Run(tc.name, func() {
suite.SetupTest() // reset

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

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

currentMetadata, err := suite.chainA.GetSimApp().ICAControllerKeeper.GetAppMetadata(suite.chainA.GetContext(), path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID)
suite.Require().NoError(err)

metadata = icatypes.NewDefaultMetadata(path.EndpointA.ConnectionID, path.EndpointB.ConnectionID)
// use the same address as the previous metadata.
metadata.Address = currentMetadata.Address

// this is the actual change to the version.
metadata.Encoding = icatypes.EncodingProto3JSON

path.EndpointA.ChannelConfig.ProposedUpgrade.Fields.Version = string(icatypes.ModuleCdc.MustMarshalJSON(&metadata))
path.EndpointB.ChannelConfig.ProposedUpgrade.Fields.Version = string(icatypes.ModuleCdc.MustMarshalJSON(&metadata))

err = path.EndpointA.ChanUpgradeInit()
suite.Require().NoError(err)

err = path.EndpointB.ChanUpgradeTry()
suite.Require().NoError(err)

counterpartyVersion = path.EndpointB.GetChannel().Version

tc.malleate() // malleate mutates test data

err = suite.chainA.GetSimApp().ICAControllerKeeper.OnChanUpgradeAck(
suite.chainA.GetContext(),
path.EndpointA.ChannelConfig.PortID,
path.EndpointA.ChannelID,
counterpartyVersion,
)

expPass := tc.expError == nil
if expPass {
suite.Require().NoError(err)
suite.Require().Equal(path.EndpointA.GetChannel().Version, counterpartyVersion)
} else {
suite.Require().ErrorIs(err, tc.expError)
}
})
}
}
Loading