Skip to content

Commit 3ff5bf8

Browse files
authored
ica: genesis state implementation (#481)
* initial genesis state draft * updating protos * including yaml tags, sorting proto file structure * updating to use range queries for active channels/interchain accounts * updating GetAllPorts test * moving test strings to expected vars
1 parent cd2f81d commit 3ff5bf8

File tree

11 files changed

+872
-46
lines changed

11 files changed

+872
-46
lines changed

docs/ibc/proto-docs.md

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@
88
- [InterchainAccount](#ibc.applications.interchain_accounts.v1.InterchainAccount)
99

1010
- [ibc/applications/interchain_accounts/v1/genesis.proto](#ibc/applications/interchain_accounts/v1/genesis.proto)
11+
- [ActiveChannel](#ibc.applications.interchain_accounts.v1.ActiveChannel)
1112
- [GenesisState](#ibc.applications.interchain_accounts.v1.GenesisState)
13+
- [RegisteredInterchainAccount](#ibc.applications.interchain_accounts.v1.RegisteredInterchainAccount)
1214

1315
- [ibc/applications/interchain_accounts/v1/query.proto](#ibc/applications/interchain_accounts/v1/query.proto)
1416
- [QueryInterchainAccountAddressRequest](#ibc.applications.interchain_accounts.v1.QueryInterchainAccountAddressRequest)
@@ -311,15 +313,49 @@ An InterchainAccount is defined as a BaseAccount & the address of the account ow
311313

312314

313315

316+
<a name="ibc.applications.interchain_accounts.v1.ActiveChannel"></a>
317+
318+
### ActiveChannel
319+
ActiveChannel contains a pairing of port ID and channel ID for an active interchain accounts channel
320+
321+
322+
| Field | Type | Label | Description |
323+
| ----- | ---- | ----- | ----------- |
324+
| `port_id` | [string](#string) | | |
325+
| `channel_id` | [string](#string) | | |
326+
327+
328+
329+
330+
331+
314332
<a name="ibc.applications.interchain_accounts.v1.GenesisState"></a>
315333

316334
### GenesisState
317-
GenesisState defines the interchain_account genesis state
335+
GenesisState defines the interchain accounts genesis state
336+
337+
338+
| Field | Type | Label | Description |
339+
| ----- | ---- | ----- | ----------- |
340+
| `active_channels` | [ActiveChannel](#ibc.applications.interchain_accounts.v1.ActiveChannel) | repeated | |
341+
| `interchain_accounts` | [RegisteredInterchainAccount](#ibc.applications.interchain_accounts.v1.RegisteredInterchainAccount) | repeated | |
342+
| `ports` | [string](#string) | repeated | |
343+
344+
345+
346+
347+
348+
349+
<a name="ibc.applications.interchain_accounts.v1.RegisteredInterchainAccount"></a>
350+
351+
### RegisteredInterchainAccount
352+
RegisteredInterchainAccount contains a pairing of controller port ID and associated interchain account address
318353

319354

320355
| Field | Type | Label | Description |
321356
| ----- | ---- | ----- | ----------- |
322357
| `port_id` | [string](#string) | | |
358+
| `account_address` | [string](#string) | | |
323359

324360

325361

modules/apps/27-interchain-accounts/genesis.go

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,20 +12,29 @@ import (
1212

1313
// InitGenesis initializes the interchain accounts application state from a provided genesis state
1414
func InitGenesis(ctx sdk.Context, keeper keeper.Keeper, state types.GenesisState) {
15-
if !keeper.IsBound(ctx, state.PortId) {
16-
cap := keeper.BindPort(ctx, state.PortId)
17-
if err := keeper.ClaimCapability(ctx, cap, host.PortPath(state.PortId)); err != nil {
18-
panic(fmt.Sprintf("could not claim port capability: %v", err))
15+
for _, portID := range state.Ports {
16+
if !keeper.IsBound(ctx, portID) {
17+
cap := keeper.BindPort(ctx, portID)
18+
if err := keeper.ClaimCapability(ctx, cap, host.PortPath(portID)); err != nil {
19+
panic(fmt.Sprintf("could not claim port capability: %v", err))
20+
}
1921
}
2022
}
21-
}
2223

23-
// ExportGenesis exports transfer module's portID into its geneis state
24-
func ExportGenesis(ctx sdk.Context, keeper keeper.Keeper) *types.GenesisState {
25-
// TODO: Using a range query with KVStorePrefixIterator export all port IDs
26-
// See https://github.com/cosmos/ibc-go/issues/448
24+
for _, ch := range state.ActiveChannels {
25+
keeper.SetActiveChannelID(ctx, ch.PortId, ch.ChannelId)
26+
}
2727

28-
return &types.GenesisState{
29-
PortId: types.PortID,
28+
for _, acc := range state.InterchainAccounts {
29+
keeper.SetInterchainAccountAddress(ctx, acc.PortId, acc.AccountAddress)
3030
}
3131
}
32+
33+
// ExportGenesis returns the interchain accounts exported genesis
34+
func ExportGenesis(ctx sdk.Context, keeper keeper.Keeper) *types.GenesisState {
35+
return types.NewGenesisState(
36+
keeper.GetAllPorts(ctx),
37+
keeper.GetAllActiveChannels(ctx),
38+
keeper.GetAllInterchainAccounts(ctx),
39+
)
40+
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
package interchain_accounts_test
2+
3+
import (
4+
ica "github.com/cosmos/ibc-go/v2/modules/apps/27-interchain-accounts"
5+
"github.com/cosmos/ibc-go/v2/modules/apps/27-interchain-accounts/types"
6+
)
7+
8+
func (suite *InterchainAccountsTestSuite) TestInitGenesis() {
9+
var (
10+
expectedChannelID string = "channel-0"
11+
)
12+
13+
suite.SetupTest()
14+
15+
genesisState := types.GenesisState{
16+
Ports: []string{types.PortID, TestPortID},
17+
ActiveChannels: []*types.ActiveChannel{
18+
{
19+
PortId: TestPortID,
20+
ChannelId: expectedChannelID,
21+
},
22+
},
23+
InterchainAccounts: []*types.RegisteredInterchainAccount{
24+
{
25+
PortId: TestPortID,
26+
AccountAddress: TestAccAddress.String(),
27+
},
28+
},
29+
}
30+
31+
ica.InitGenesis(suite.chainA.GetContext(), suite.chainA.GetSimApp().ICAKeeper, genesisState)
32+
33+
channelID, found := suite.chainA.GetSimApp().ICAKeeper.GetActiveChannelID(suite.chainA.GetContext(), TestPortID)
34+
suite.Require().True(found)
35+
suite.Require().Equal(expectedChannelID, channelID)
36+
37+
accountAdrr, found := suite.chainA.GetSimApp().ICAKeeper.GetInterchainAccountAddress(suite.chainA.GetContext(), TestPortID)
38+
suite.Require().True(found)
39+
suite.Require().Equal(TestAccAddress.String(), accountAdrr)
40+
}
41+
42+
func (suite *InterchainAccountsTestSuite) TestExportGenesis() {
43+
suite.SetupTest()
44+
path := NewICAPath(suite.chainA, suite.chainB)
45+
suite.coordinator.SetupConnections(path)
46+
47+
err := SetupICAPath(path, TestOwnerAddress)
48+
suite.Require().NoError(err)
49+
50+
genesisState := ica.ExportGenesis(suite.chainA.GetContext(), suite.chainA.GetSimApp().ICAKeeper)
51+
52+
suite.Require().Equal([]string{types.PortID, TestPortID}, genesisState.GetPorts())
53+
54+
suite.Require().Equal(path.EndpointA.ChannelID, genesisState.ActiveChannels[0].ChannelId)
55+
suite.Require().Equal(path.EndpointA.ChannelConfig.PortID, genesisState.ActiveChannels[0].PortId)
56+
57+
suite.Require().Equal(TestAccAddress.String(), genesisState.InterchainAccounts[0].AccountAddress)
58+
suite.Require().Equal(path.EndpointA.ChannelConfig.PortID, genesisState.InterchainAccounts[0].PortId)
59+
}

modules/apps/27-interchain-accounts/keeper/keeper.go

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,27 @@ func (k Keeper) GetActiveChannelID(ctx sdk.Context, portID string) (string, bool
113113
return string(store.Get(key)), true
114114
}
115115

116+
// GetAllActiveChannels returns a list of all active interchain accounts channels and their associated port identifiers
117+
func (k Keeper) GetAllActiveChannels(ctx sdk.Context) []*types.ActiveChannel {
118+
store := ctx.KVStore(k.storeKey)
119+
iterator := sdk.KVStorePrefixIterator(store, []byte(types.ActiveChannelKeyPrefix))
120+
defer iterator.Close()
121+
122+
var activeChannels []*types.ActiveChannel
123+
for ; iterator.Valid(); iterator.Next() {
124+
keySplit := strings.Split(string(iterator.Key()), "/")
125+
126+
ch := &types.ActiveChannel{
127+
PortId: keySplit[1],
128+
ChannelId: string(iterator.Value()),
129+
}
130+
131+
activeChannels = append(activeChannels, ch)
132+
}
133+
134+
return activeChannels
135+
}
136+
116137
// SetActiveChannelID stores the active channelID, keyed by the provided portID
117138
func (k Keeper) SetActiveChannelID(ctx sdk.Context, portID, channelID string) {
118139
store := ctx.KVStore(k.storeKey)
@@ -143,6 +164,26 @@ func (k Keeper) GetInterchainAccountAddress(ctx sdk.Context, portID string) (str
143164
return string(store.Get(key)), true
144165
}
145166

167+
// GetAllInterchainAccounts returns a list of all registered interchain account addresses and their associated controller port identifiers
168+
func (k Keeper) GetAllInterchainAccounts(ctx sdk.Context) []*types.RegisteredInterchainAccount {
169+
store := ctx.KVStore(k.storeKey)
170+
iterator := sdk.KVStorePrefixIterator(store, []byte(types.OwnerKeyPrefix))
171+
172+
var interchainAccounts []*types.RegisteredInterchainAccount
173+
for ; iterator.Valid(); iterator.Next() {
174+
keySplit := strings.Split(string(iterator.Key()), "/")
175+
176+
acc := &types.RegisteredInterchainAccount{
177+
PortId: keySplit[1],
178+
AccountAddress: string(iterator.Value()),
179+
}
180+
181+
interchainAccounts = append(interchainAccounts, acc)
182+
}
183+
184+
return interchainAccounts
185+
}
186+
146187
// SetInterchainAccountAddress stores the InterchainAccount address, keyed by the associated portID
147188
func (k Keeper) SetInterchainAccountAddress(ctx sdk.Context, portID string, address string) {
148189
store := ctx.KVStore(k.storeKey)

modules/apps/27-interchain-accounts/keeper/keeper_test.go

Lines changed: 74 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -116,9 +116,11 @@ func (suite *KeeperTestSuite) TestGetAllPorts() {
116116
err := SetupICAPath(path, TestOwnerAddress)
117117
suite.Require().NoError(err)
118118

119+
expectedPorts := []string{types.PortID, TestPortID}
120+
119121
ports := suite.chainA.GetSimApp().ICAKeeper.GetAllPorts(suite.chainA.GetContext())
120-
suite.Require().Contains(ports, types.PortID)
121-
suite.Require().Contains(ports, TestPortID)
122+
suite.Require().Len(ports, len(expectedPorts))
123+
suite.Require().Equal(expectedPorts, ports)
122124
}
123125

124126
func (suite *KeeperTestSuite) TestGetInterchainAccountAddress() {
@@ -141,6 +143,68 @@ func (suite *KeeperTestSuite) TestGetInterchainAccountAddress() {
141143
suite.Require().Empty(retrievedAddr)
142144
}
143145

146+
func (suite *KeeperTestSuite) TestGetAllActiveChannels() {
147+
var (
148+
expectedChannelID string = "test-channel"
149+
expectedPortID string = "test-port"
150+
)
151+
152+
suite.SetupTest()
153+
path := NewICAPath(suite.chainA, suite.chainB)
154+
suite.coordinator.SetupConnections(path)
155+
156+
err := SetupICAPath(path, TestOwnerAddress)
157+
suite.Require().NoError(err)
158+
159+
suite.chainA.GetSimApp().ICAKeeper.SetActiveChannelID(suite.chainA.GetContext(), expectedPortID, expectedChannelID)
160+
161+
expectedChannels := []*types.ActiveChannel{
162+
{
163+
PortId: TestPortID,
164+
ChannelId: path.EndpointA.ChannelID,
165+
},
166+
{
167+
PortId: expectedPortID,
168+
ChannelId: expectedChannelID,
169+
},
170+
}
171+
172+
activeChannels := suite.chainA.GetSimApp().ICAKeeper.GetAllActiveChannels(suite.chainA.GetContext())
173+
suite.Require().Len(activeChannels, len(expectedChannels))
174+
suite.Require().Equal(expectedChannels, activeChannels)
175+
}
176+
177+
func (suite *KeeperTestSuite) TestGetAllInterchainAccounts() {
178+
var (
179+
expectedAccAddr string = "test-acc-addr"
180+
expectedPortID string = "test-port"
181+
)
182+
183+
suite.SetupTest()
184+
path := NewICAPath(suite.chainA, suite.chainB)
185+
suite.coordinator.SetupConnections(path)
186+
187+
err := SetupICAPath(path, TestOwnerAddress)
188+
suite.Require().NoError(err)
189+
190+
suite.chainA.GetSimApp().ICAKeeper.SetInterchainAccountAddress(suite.chainA.GetContext(), expectedPortID, expectedAccAddr)
191+
192+
expectedAccounts := []*types.RegisteredInterchainAccount{
193+
{
194+
PortId: TestPortID,
195+
AccountAddress: TestAccAddress.String(),
196+
},
197+
{
198+
PortId: expectedPortID,
199+
AccountAddress: expectedAccAddr,
200+
},
201+
}
202+
203+
interchainAccounts := suite.chainA.GetSimApp().ICAKeeper.GetAllInterchainAccounts(suite.chainA.GetContext())
204+
suite.Require().Len(interchainAccounts, len(expectedAccounts))
205+
suite.Require().Equal(expectedAccounts, interchainAccounts)
206+
}
207+
144208
func (suite *KeeperTestSuite) TestIsActiveChannel() {
145209
suite.SetupTest() // reset
146210
path := NewICAPath(suite.chainA, suite.chainB)
@@ -156,12 +220,16 @@ func (suite *KeeperTestSuite) TestIsActiveChannel() {
156220
}
157221

158222
func (suite *KeeperTestSuite) TestSetInterchainAccountAddress() {
159-
expectedAddr, portID := "address", "port"
160-
suite.chainA.GetSimApp().ICAKeeper.SetInterchainAccountAddress(suite.chainA.GetContext(), portID, expectedAddr)
223+
var (
224+
expectedAccAddr string = "test-acc-addr"
225+
expectedPortID string = "test-port"
226+
)
227+
228+
suite.chainA.GetSimApp().ICAKeeper.SetInterchainAccountAddress(suite.chainA.GetContext(), expectedPortID, expectedAccAddr)
161229

162-
retrievedAddr, found := suite.chainA.GetSimApp().ICAKeeper.GetInterchainAccountAddress(suite.chainA.GetContext(), portID)
230+
retrievedAddr, found := suite.chainA.GetSimApp().ICAKeeper.GetInterchainAccountAddress(suite.chainA.GetContext(), expectedPortID)
163231
suite.Require().True(found)
164-
suite.Require().Equal(expectedAddr, retrievedAddr)
232+
suite.Require().Equal(expectedAccAddr, retrievedAddr)
165233
}
166234

167235
func (suite *KeeperTestSuite) SetupICAPath(path *ibctesting.Path, owner string) error {
Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,18 @@
11
package types
22

3+
// DefaultGenesis creates and returns the default interchain accounts GenesisState
4+
// The default GenesisState includes the standard port identifier to which all host chains must bind
35
func DefaultGenesis() *GenesisState {
46
return &GenesisState{
5-
PortId: PortID,
7+
Ports: []string{PortID},
8+
}
9+
}
10+
11+
// NewGenesisState creates a returns a new GenesisState instance
12+
func NewGenesisState(ports []string, channels []*ActiveChannel, accounts []*RegisteredInterchainAccount) *GenesisState {
13+
return &GenesisState{
14+
ActiveChannels: channels,
15+
InterchainAccounts: accounts,
16+
Ports: ports,
617
}
718
}

0 commit comments

Comments
 (0)