Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit f7d4256

Browse files
damiannolanmergify[bot]
authored andcommittedAug 31, 2022
chore: ics27 channel capability migrations (#2134)
* wip initial commit * draft migration completed * removing unnecessary storekey arg * additional cleanup * adding updates to migrations and tests additional assertions * updating and moving migrations code * adding additional checks to tests * cleaning up tests * cleaning up tests * updating inline doc comments, checking err return * using InitMemStore in favour of InitializeCapability, adjusting tests * updating migration code to run against persisted state only, adapting tests * updating inline comments * adding changelog entry (cherry picked from commit 0a8602c) # Conflicts: # CHANGELOG.md
1 parent cc16ae4 commit f7d4256

File tree

3 files changed

+283
-0
lines changed

3 files changed

+283
-0
lines changed
 

‎CHANGELOG.md

+61
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,67 @@ Ref: https://keepachangelog.com/en/1.0.0/
5151

5252
### State Machine Breaking
5353

54+
<<<<<<< HEAD
55+
=======
56+
### Improvements
57+
58+
* (apps/27-interchain-accounts) [\#2133](https://github.com/cosmos/ibc-go/pull/2133) Generates genesis protos in a separate directory to avoid circular import errors. The protobuf package name has changed for the genesis types.
59+
* (linting) [\#1418](https://github.com/cosmos/ibc-go/pull/1418) Fix linting errors, resulting compatiblity with go1.18 linting style, golangci-lint 1.46.2 and the revivie linter. This caused breaking changes in core/04-channel, core/ante, and the testing library.
60+
* (modules/light-clients/07-tendermint) [\#1713](https://github.com/cosmos/ibc-go/pull/1713) Allow client upgrade proposals to update `TrustingPeriod`. See ADR-026 for context.
61+
* (modules/core/02-client) [\#1188](https://github.com/cosmos/ibc-go/pull/1188/files) Routing `MsgSubmitMisbehaviour` to `UpdateClient` keeper function. Deprecating `SubmitMisbehaviour` endpoint.
62+
* (modules/core/02-client) [\#1208](https://github.com/cosmos/ibc-go/pull/1208) Replace `CheckHeaderAndUpdateState` usage in 02-client with calls to `VerifyClientMessage`, `CheckForMisbehaviour`, `UpdateStateOnMisbehaviour` and `UpdateState`.
63+
* (modules/light-clients/09-localhost) [\#1187](https://github.com/cosmos/ibc-go/pull/1187/) Removing localhost light client implementation as it is not functional. An upgrade handler is provided in `modules/migrations/v5` to prune `09-localhost` clients and consensus states from the store.
64+
* [\#1186](https://github.com/cosmos/ibc-go/pull/1186/files) Removing `GetRoot` function from ConsensusState interface in `02-client`. `GetRoot` is unused by core IBC.
65+
* (modules/core/02-client) [\#1196](https://github.com/cosmos/ibc-go/pull/1196) Adding VerifyClientMessage to ClientState interface.
66+
* (modules/core/02-client) [\#1198](https://github.com/cosmos/ibc-go/pull/1198) Adding UpdateStateOnMisbehaviour to ClientState interface.
67+
* (modules/core/02-client) [\#1170](https://github.com/cosmos/ibc-go/pull/1170) Updating `ClientUpdateProposal` to set client state in lightclient implementations `CheckSubstituteAndUpdateState` methods.
68+
* (modules/core/02-client) [\#1197](https://github.com/cosmos/ibc-go/pull/1197) Adding `CheckForMisbehaviour` to `ClientState` interface.
69+
* (modules/core/02-client) [\#1195](https://github.com/cosmos/ibc-go/pull/1210) Removing `CheckHeaderAndUpdateState` from `ClientState` interface & associated light client implementations.
70+
* (modules/core/02-client) [\#1189](https://github.com/cosmos/ibc-go/pull/1212) Removing `CheckMisbehaviourAndUpdateState` from `ClientState` interface & associated light client implementations.
71+
* (modules/core/exported) [\#1206](https://github.com/cosmos/ibc-go/pull/1206) Adding new method `UpdateState` to `ClientState` interface.
72+
* (modules/core/02-client) [\#1741](https://github.com/cosmos/ibc-go/pull/1741) Emitting a new `upgrade_chain` event upon setting upgrade consensus state.
73+
* (client) [\#724](https://github.com/cosmos/ibc-go/pull/724) `IsRevisionFormat` and `IsClientIDFormat` have been updated to disallow newlines before the dash used to separate the chainID and revision number, and the client type and client sequence.
74+
* (02-client/cli) [\#897](https://github.com/cosmos/ibc-go/pull/897) Remove `GetClientID()` from `Misbehaviour` interface. Submit client misbehaviour cli command requires an explicit client id now.
75+
* (06-solomachine) [\#1972](https://github.com/cosmos/ibc-go/pull/1972) Solo machine implementation of `ZeroCustomFields` fn now panics as the fn is only used for upgrades which solo machine does not support.
76+
* (apps/27-interchain-accounts) [\#2102](https://github.com/cosmos/ibc-go/pull/2102) ICS27 controller middleware now supports a nil underlying application. This allows chains to make use of interchain accounts with existing auth mechanisms such as x/group and x/gov.
77+
* (apps/27-interchain-accounts) [\#2146](https://github.com/cosmos/ibc-go/pull/2146) ICS27 controller now claims the channel capability passed via ibc core, and passes `nil` to the underlying app callback. The channel capability arg in `SendTx` is now ignored and looked up internally.
78+
* (apps/27-interchain-accounts) [\#2134](https://github.com/cosmos/ibc-go/pull/2134) Adding upgrade handler to ICS27 `controller` submodule for migration of channel capabilities. This upgrade handler migrates ownership of channel capabilities from the underlying application to the ICS27 `controller` submodule.
79+
80+
### Features
81+
82+
### Bug Fixes
83+
84+
* (makefile) [\#1785](https://github.com/cosmos/ibc-go/pull/1785) Fetch the correct versions of protocol buffers dependencies from tendermint, cosmos-sdk, and ics23.
85+
* (light-clients/solomachine) [#1839](https://github.com/cosmos/ibc-go/issues/1839) Fixed usage of the new diversifier in validation of changing diversifiers for the solo machine. The current diversifier must sign over the new diversifier.
86+
* (light-clients/07-tendermint) [\#1674](https://github.com/cosmos/ibc-go/pull/1674) Submitted ClientState is zeroed out before checking the proof in order to prevent the proposal from containing information governance is not actually voting on.
87+
* (modules/core/02-client)[\#1676](https://github.com/cosmos/ibc-go/pull/1676) ClientState must be zeroed out for `UpgradeProposals` to pass validation. This prevents a proposal containing information governance is not actually voting on.
88+
89+
## [v4.0.0](https://github.com/cosmos/ibc-go/releases/tag/v4.0.0) - 2022-08-12
90+
91+
### Dependencies
92+
93+
* [\#1627](https://github.com/cosmos/ibc-go/pull/1627) Bump Go version to 1.18
94+
* [\#1905](https://github.com/cosmos/ibc-go/pull/1905) Bump SDK version to v0.45.7
95+
96+
### API Breaking
97+
98+
* (core/04-channel) [\#1792](https://github.com/cosmos/ibc-go/pull/1792) Remove `PreviousChannelID` from `NewMsgChannelOpenTry` arguments. `MsgChannelOpenTry.ValidateBasic()` returns error if the deprecated `PreviousChannelID` is not empty.
99+
* (core/03-connection) [\#1797](https://github.com/cosmos/ibc-go/pull/1797) Remove `PreviousConnectionID` from `NewMsgConnectionOpenTry` arguments. `MsgConnectionOpenTry.ValidateBasic()` returns error if the deprecated `PreviousConnectionID` is not empty.
100+
* (modules/core/03-connection) [\#1672](https://github.com/cosmos/ibc-go/pull/1672) Remove crossing hellos from connection handshakes. The `PreviousConnectionId` in `MsgConnectionOpenTry` has been deprecated.
101+
* (modules/core/04-channel) [\#1317](https://github.com/cosmos/ibc-go/pull/1317) Remove crossing hellos from channel handshakes. The `PreviousChannelId` in `MsgChannelOpenTry` has been deprecated.
102+
* (transfer) [\#1250](https://github.com/cosmos/ibc-go/pull/1250) Deprecate `GetTransferAccount` since the `transfer` module account is never used.
103+
* (channel) [\#1283](https://github.com/cosmos/ibc-go/pull/1283) The `OnChanOpenInit` application callback now returns a version string in line with the latest [spec changes](https://github.com/cosmos/ibc/pull/629).
104+
* (modules/29-fee)[\#1338](https://github.com/cosmos/ibc-go/pull/1338) Renaming `Result` field in `IncentivizedAcknowledgement` to `AppAcknowledgement`.
105+
* (modules/29-fee)[\#1343](https://github.com/cosmos/ibc-go/pull/1343) Renaming `KeyForwardRelayerAddress` to `KeyRelayerAddressForAsyncAck`, and `ParseKeyForwardRelayerAddress` to `ParseKeyRelayerAddressForAsyncAck`.
106+
* (apps/27-interchain-accounts)[\#1432](https://github.com/cosmos/ibc-go/pull/1432) Updating `RegisterInterchainAccount` to include an additional `version` argument, supporting ICS29 fee middleware functionality in ICS27 interchain accounts.
107+
* (apps/27-interchain-accounts)[\#1565](https://github.com/cosmos/ibc-go/pull/1565) Removing `NewErrorAcknowledgement` in favour of `channeltypes.NewErrorAcknowledgement`.
108+
* (transfer)[\#1565](https://github.com/cosmos/ibc-go/pull/1565) Removing `NewErrorAcknowledgement` in favour of `channeltypes.NewErrorAcknowledgement`.
109+
* (channel)[\#1565](https://github.com/cosmos/ibc-go/pull/1565) Updating `NewErrorAcknowledgement` to accept an error instead of a string and removing the possibility of non-deterministic writes to application state.
110+
* (core/04-channel)[\#1636](https://github.com/cosmos/ibc-go/pull/1636) Removing `SplitChannelVersion` and `MergeChannelVersions` functions since they are not used.
111+
112+
### State Machine Breaking
113+
114+
>>>>>>> 0a8602c (chore: ics27 channel capability migrations (#2134))
54115
* (apps/transfer) [\#1907](https://github.com/cosmos/ibc-go/pull/1907) Blocked module account addresses are no longer allowed to send IBC transfers.
55116
* (apps/27-interchain-accounts) [\#1882](https://github.com/cosmos/ibc-go/pull/1882) Explicitly check length of interchain account packet data in favour of nil check.
56117

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
package v5
2+
3+
import (
4+
"github.com/cosmos/cosmos-sdk/codec"
5+
"github.com/cosmos/cosmos-sdk/store/prefix"
6+
storetypes "github.com/cosmos/cosmos-sdk/store/types"
7+
sdk "github.com/cosmos/cosmos-sdk/types"
8+
capabilitykeeper "github.com/cosmos/cosmos-sdk/x/capability/keeper"
9+
capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types"
10+
11+
"github.com/cosmos/ibc-go/v5/modules/apps/27-interchain-accounts/controller/types"
12+
)
13+
14+
// MigrateICS27ChannelCapability performs a search on a prefix store using the provided store key and module name.
15+
// It retrieves the associated channel capability index and reassigns ownership to the ICS27 controller submodule.
16+
func MigrateICS27ChannelCapability(
17+
ctx sdk.Context,
18+
cdc codec.BinaryCodec,
19+
storeKey storetypes.StoreKey,
20+
capabilityKeeper *capabilitykeeper.Keeper,
21+
module string, // the name of the scoped keeper for the underlying app module
22+
) error {
23+
// construct a prefix store using the x/capability index prefix: index->capability owners
24+
prefixStore := prefix.NewStore(ctx.KVStore(storeKey), capabilitytypes.KeyPrefixIndexCapability)
25+
iterator := sdk.KVStorePrefixIterator(prefixStore, nil)
26+
defer iterator.Close()
27+
28+
for ; iterator.Valid(); iterator.Next() {
29+
// unmarshal the capability index value and set of owners
30+
index := capabilitytypes.IndexFromKey(iterator.Key())
31+
32+
var owners capabilitytypes.CapabilityOwners
33+
cdc.MustUnmarshal(iterator.Value(), &owners)
34+
35+
for _, owner := range owners.GetOwners() {
36+
if owner.Module == module {
37+
// remove the owner from the set
38+
owners.Remove(owner)
39+
40+
// reassign the owner module to icacontroller
41+
owner.Module = types.SubModuleName
42+
43+
// add the controller submodule to the set of owners
44+
if err := owners.Set(owner); err != nil {
45+
return err
46+
}
47+
48+
// set the new owners for the current capability index
49+
capabilityKeeper.SetOwners(ctx, index, owners)
50+
}
51+
}
52+
}
53+
54+
// initialise the x/capability memstore
55+
capabilityKeeper.InitMemStore(ctx)
56+
57+
return nil
58+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
package v5_test
2+
3+
import (
4+
"testing"
5+
6+
capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types"
7+
"github.com/stretchr/testify/suite"
8+
9+
v5 "github.com/cosmos/ibc-go/v5/modules/apps/27-interchain-accounts/controller/migrations/v5"
10+
"github.com/cosmos/ibc-go/v5/modules/apps/27-interchain-accounts/controller/types"
11+
icatypes "github.com/cosmos/ibc-go/v5/modules/apps/27-interchain-accounts/types"
12+
channeltypes "github.com/cosmos/ibc-go/v5/modules/core/04-channel/types"
13+
host "github.com/cosmos/ibc-go/v5/modules/core/24-host"
14+
ibctesting "github.com/cosmos/ibc-go/v5/testing"
15+
ibcmock "github.com/cosmos/ibc-go/v5/testing/mock"
16+
)
17+
18+
type MigrationsTestSuite struct {
19+
suite.Suite
20+
21+
chainA *ibctesting.TestChain
22+
chainB *ibctesting.TestChain
23+
24+
coordinator *ibctesting.Coordinator
25+
path *ibctesting.Path
26+
}
27+
28+
func (suite *MigrationsTestSuite) SetupTest() {
29+
suite.coordinator = ibctesting.NewCoordinator(suite.T(), 2)
30+
31+
suite.chainA = suite.coordinator.GetChain(ibctesting.GetChainID(1))
32+
suite.chainB = suite.coordinator.GetChain(ibctesting.GetChainID(2))
33+
34+
suite.path = ibctesting.NewPath(suite.chainA, suite.chainB)
35+
suite.path.EndpointA.ChannelConfig.PortID = icatypes.PortID
36+
suite.path.EndpointB.ChannelConfig.PortID = icatypes.PortID
37+
suite.path.EndpointA.ChannelConfig.Order = channeltypes.ORDERED
38+
suite.path.EndpointB.ChannelConfig.Order = channeltypes.ORDERED
39+
suite.path.EndpointA.ChannelConfig.Version = icatypes.NewDefaultMetadataString(ibctesting.FirstConnectionID, ibctesting.FirstConnectionID)
40+
suite.path.EndpointB.ChannelConfig.Version = icatypes.NewDefaultMetadataString(ibctesting.FirstConnectionID, ibctesting.FirstConnectionID)
41+
}
42+
43+
func (suite *MigrationsTestSuite) SetupPath() error {
44+
if err := suite.RegisterInterchainAccount(suite.path.EndpointA, ibctesting.TestAccAddress); err != nil {
45+
return err
46+
}
47+
48+
if err := suite.path.EndpointB.ChanOpenTry(); err != nil {
49+
return err
50+
}
51+
52+
if err := suite.path.EndpointA.ChanOpenAck(); err != nil {
53+
return err
54+
}
55+
56+
if err := suite.path.EndpointB.ChanOpenConfirm(); err != nil {
57+
return err
58+
}
59+
60+
return nil
61+
}
62+
63+
func (suite *MigrationsTestSuite) RegisterInterchainAccount(endpoint *ibctesting.Endpoint, owner string) error {
64+
portID, err := icatypes.NewControllerPortID(owner)
65+
if err != nil {
66+
return err
67+
}
68+
69+
channelSequence := endpoint.Chain.App.GetIBCKeeper().ChannelKeeper.GetNextChannelSequence(endpoint.Chain.GetContext())
70+
71+
if err := endpoint.Chain.GetSimApp().ICAControllerKeeper.RegisterInterchainAccount(endpoint.Chain.GetContext(), endpoint.ConnectionID, owner, endpoint.ChannelConfig.Version); err != nil {
72+
return err
73+
}
74+
75+
// commit state changes for proof verification
76+
endpoint.Chain.NextBlock()
77+
78+
// update port/channel ids
79+
endpoint.ChannelID = channeltypes.FormatChannelIdentifier(channelSequence)
80+
endpoint.ChannelConfig.PortID = portID
81+
82+
return nil
83+
}
84+
85+
func TestKeeperTestSuite(t *testing.T) {
86+
suite.Run(t, new(MigrationsTestSuite))
87+
}
88+
89+
func (suite *MigrationsTestSuite) TestMigrateICS27ChannelCapability() {
90+
suite.SetupTest()
91+
suite.coordinator.SetupConnections(suite.path)
92+
93+
err := suite.SetupPath()
94+
suite.Require().NoError(err)
95+
96+
// create and claim a new capability with ibc/mock for "channel-1"
97+
// note: suite.SetupPath() now claims the chanel capability using icacontroller for "channel-0"
98+
capName := host.ChannelCapabilityPath(suite.path.EndpointA.ChannelConfig.PortID, channeltypes.FormatChannelIdentifier(1))
99+
100+
cap, err := suite.chainA.GetSimApp().ScopedIBCKeeper.NewCapability(suite.chainA.GetContext(), capName)
101+
suite.Require().NoError(err)
102+
103+
err = suite.chainA.GetSimApp().ScopedICAMockKeeper.ClaimCapability(suite.chainA.GetContext(), cap, capName)
104+
suite.Require().NoError(err)
105+
106+
// assert the capability is owned by the mock module
107+
cap, found := suite.chainA.GetSimApp().ScopedICAMockKeeper.GetCapability(suite.chainA.GetContext(), capName)
108+
suite.Require().NotNil(cap)
109+
suite.Require().True(found)
110+
111+
isAuthenticated := suite.chainA.GetSimApp().ScopedICAMockKeeper.AuthenticateCapability(suite.chainA.GetContext(), cap, capName)
112+
suite.Require().True(isAuthenticated)
113+
114+
cap, found = suite.chainA.GetSimApp().ScopedICAControllerKeeper.GetCapability(suite.chainA.GetContext(), capName)
115+
suite.Require().Nil(cap)
116+
suite.Require().False(found)
117+
118+
suite.ResetMemStore() // empty the x/capability in-memory store
119+
120+
err = v5.MigrateICS27ChannelCapability(
121+
suite.chainA.GetContext(),
122+
suite.chainA.Codec,
123+
suite.chainA.GetSimApp().GetKey(capabilitytypes.StoreKey),
124+
suite.chainA.GetSimApp().CapabilityKeeper,
125+
ibcmock.ModuleName+types.SubModuleName,
126+
)
127+
128+
suite.Require().NoError(err)
129+
130+
// assert the capability is now owned by the ICS27 controller submodule
131+
cap, found = suite.chainA.GetSimApp().ScopedICAControllerKeeper.GetCapability(suite.chainA.GetContext(), capName)
132+
suite.Require().NotNil(cap)
133+
suite.Require().True(found)
134+
135+
isAuthenticated = suite.chainA.GetSimApp().ScopedICAControllerKeeper.AuthenticateCapability(suite.chainA.GetContext(), cap, capName)
136+
suite.Require().True(isAuthenticated)
137+
138+
cap, found = suite.chainA.GetSimApp().ScopedICAMockKeeper.GetCapability(suite.chainA.GetContext(), capName)
139+
suite.Require().Nil(cap)
140+
suite.Require().False(found)
141+
142+
// ensure channel capability for "channel-0" is still owned by the controller
143+
capName = host.ChannelCapabilityPath(suite.path.EndpointA.ChannelConfig.PortID, suite.path.EndpointA.ChannelID)
144+
cap, found = suite.chainA.GetSimApp().ScopedICAControllerKeeper.GetCapability(suite.chainA.GetContext(), capName)
145+
suite.Require().NotNil(cap)
146+
suite.Require().True(found)
147+
148+
isAuthenticated = suite.chainA.GetSimApp().ScopedICAControllerKeeper.AuthenticateCapability(suite.chainA.GetContext(), cap, capName)
149+
suite.Require().True(isAuthenticated)
150+
}
151+
152+
// ResetMemstore removes all existing fwd and rev capability kv pairs and deletes `KeyMemInitialised` from the x/capability memstore.
153+
// This effectively mocks a new chain binary being started. Migration code is run against persisted state only and allows the memstore to be reinitialised.
154+
func (suite *MigrationsTestSuite) ResetMemStore() {
155+
memStore := suite.chainA.GetContext().KVStore(suite.chainA.GetSimApp().GetMemKey(capabilitytypes.MemStoreKey))
156+
memStore.Delete(capabilitytypes.KeyMemInitialized)
157+
158+
iterator := memStore.Iterator(nil, nil)
159+
defer iterator.Close()
160+
161+
for ; iterator.Valid(); iterator.Next() {
162+
memStore.Delete(iterator.Key())
163+
}
164+
}

0 commit comments

Comments
 (0)
Please sign in to comment.