Skip to content

Commit

Permalink
Problem: interchain-accounts module is not integrated (crypto-org-cha…
Browse files Browse the repository at this point in the history
…in#541)

* Problem: interchain-accounts module is not integrated

Closes: crypto-org-chain#540

Solution:
- integrate ica controller module

add ica integration tests

regen proto

temp

cleanup

fix integration test

Update integration_tests/test_ibc.py

cleanup

icaauth -> icactl

gen proto

fix integration test

fix conflicts

add v0.8.0 upgrade test and comment

use flake-compat to build v0.7.0 binary for upgrade test

fix integration test

use flake-compat to build v0.7.0 binary for upgrade test

fix integration test

fix rebase

fix key_name

* update swagger ui
  • Loading branch information
yihuang authored and mmsqe committed Aug 29, 2023
1 parent 57adff9 commit 5810f9c
Show file tree
Hide file tree
Showing 40 changed files with 4,610 additions and 19 deletions.
104 changes: 85 additions & 19 deletions app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,11 @@ import (
upgradeclient "github.com/cosmos/cosmos-sdk/x/upgrade/client"
upgradekeeper "github.com/cosmos/cosmos-sdk/x/upgrade/keeper"
upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types"
ica "github.com/cosmos/ibc-go/v6/modules/apps/27-interchain-accounts"
icacontroller "github.com/cosmos/ibc-go/v6/modules/apps/27-interchain-accounts/controller"
icacontrollerkeeper "github.com/cosmos/ibc-go/v6/modules/apps/27-interchain-accounts/controller/keeper"
icacontrollertypes "github.com/cosmos/ibc-go/v6/modules/apps/27-interchain-accounts/controller/types"
icatypes "github.com/cosmos/ibc-go/v6/modules/apps/27-interchain-accounts/types"
ibcfee "github.com/cosmos/ibc-go/v6/modules/apps/29-fee"
ibcfeekeeper "github.com/cosmos/ibc-go/v6/modules/apps/29-fee/keeper"
ibcfeetypes "github.com/cosmos/ibc-go/v6/modules/apps/29-fee/types"
Expand Down Expand Up @@ -124,6 +129,9 @@ import (
gravitytypes "github.com/peggyjv/gravity-bridge/module/v2/x/gravity/types"

// this line is used by starport scaffolding # stargate/app/moduleImport
icactlmodule "github.com/crypto-org-chain/cronos/v2/x/icactl"
icactlmodulekeeper "github.com/crypto-org-chain/cronos/v2/x/icactl/keeper"
icactlmoduletypes "github.com/crypto-org-chain/cronos/v2/x/icactl/types"

memiavlstore "github.com/crypto-org-chain/cronos/store"
memiavlrootmulti "github.com/crypto-org-chain/cronos/store/rootmulti"
Expand Down Expand Up @@ -190,6 +198,7 @@ var (
govtypes.ModuleName: {authtypes.Burner},
ibctransfertypes.ModuleName: {authtypes.Minter, authtypes.Burner},
ibcfeetypes.ModuleName: nil,
icatypes.ModuleName: nil,
evmtypes.ModuleName: {authtypes.Minter, authtypes.Burner}, // used for secure addition and subtraction of balance using module account
gravitytypes.ModuleName: {authtypes.Minter, authtypes.Burner},
cronostypes.ModuleName: {authtypes.Minter, authtypes.Burner},
Expand Down Expand Up @@ -229,6 +238,8 @@ func GenModuleBasics() module.BasicManager {
authzmodule.AppModuleBasic{},
ibc.AppModuleBasic{},
transfer.AppModuleBasic{},
ica.AppModuleBasic{},
icactlmodule.AppModuleBasic{},
vesting.AppModuleBasic{},
ibcfee.AppModuleBasic{},
evm.AppModuleBasic{},
Expand Down Expand Up @@ -289,27 +300,31 @@ type App struct {
memKeys map[string]*storetypes.MemoryStoreKey

// keepers
AccountKeeper authkeeper.AccountKeeper
BankKeeper bankkeeper.Keeper
CapabilityKeeper *capabilitykeeper.Keeper
StakingKeeper stakingkeeper.Keeper
SlashingKeeper slashingkeeper.Keeper
MintKeeper mintkeeper.Keeper
DistrKeeper distrkeeper.Keeper
GovKeeper govkeeper.Keeper
CrisisKeeper crisiskeeper.Keeper
UpgradeKeeper upgradekeeper.Keeper
ParamsKeeper paramskeeper.Keeper
IBCKeeper *ibckeeper.Keeper // IBC Keeper must be a pointer in the app, so we can SetRouter on it correctly
IBCFeeKeeper ibcfeekeeper.Keeper
EvidenceKeeper evidencekeeper.Keeper
TransferKeeper ibctransferkeeper.Keeper
FeeGrantKeeper feegrantkeeper.Keeper
AuthzKeeper authzkeeper.Keeper
AccountKeeper authkeeper.AccountKeeper
BankKeeper bankkeeper.Keeper
CapabilityKeeper *capabilitykeeper.Keeper
StakingKeeper stakingkeeper.Keeper
SlashingKeeper slashingkeeper.Keeper
MintKeeper mintkeeper.Keeper
DistrKeeper distrkeeper.Keeper
GovKeeper govkeeper.Keeper
CrisisKeeper crisiskeeper.Keeper
UpgradeKeeper upgradekeeper.Keeper
ParamsKeeper paramskeeper.Keeper
IBCKeeper *ibckeeper.Keeper // IBC Keeper must be a pointer in the app, so we can SetRouter on it correctly
IBCFeeKeeper ibcfeekeeper.Keeper
TransferKeeper ibctransferkeeper.Keeper
ICAControllerKeeper icacontrollerkeeper.Keeper
ICAAuthKeeper icactlmodulekeeper.Keeper
EvidenceKeeper evidencekeeper.Keeper
FeeGrantKeeper feegrantkeeper.Keeper
AuthzKeeper authzkeeper.Keeper

// make scoped keepers public for test purposes
ScopedIBCKeeper capabilitykeeper.ScopedKeeper
ScopedTransferKeeper capabilitykeeper.ScopedKeeper
ScopedIBCKeeper capabilitykeeper.ScopedKeeper
ScopedTransferKeeper capabilitykeeper.ScopedKeeper
ScopedICAControllerKeeper capabilitykeeper.ScopedKeeper
ScopedICAAuthKeeper capabilitykeeper.ScopedKeeper

// Ethermint keepers
EvmKeeper *evmkeeper.Keeper
Expand Down Expand Up @@ -358,6 +373,10 @@ func New(
fmt.Printf("failed to load state streaming: %s", err)
os.Exit(1)
}
if experimental {
storeKeys = append(storeKeys, gravitytypes.StoreKey)
}
keys := sdk.NewKVStoreKeys(storeKeys...)

// wire up the versiondb's `StreamingService` and `MultiStore`.
streamers := cast.ToStringSlice(appOpts.Get("store.streamers"))
Expand Down Expand Up @@ -392,6 +411,8 @@ func New(
// grant capabilities for the ibc and ibc-transfer modules
scopedIBCKeeper := app.CapabilityKeeper.ScopeToModule(ibchost.ModuleName)
scopedTransferKeeper := app.CapabilityKeeper.ScopeToModule(ibctransfertypes.ModuleName)
scopedICAControllerKeeper := app.CapabilityKeeper.ScopeToModule(icacontrollertypes.SubModuleName)
scopedICAAuthKeeper := app.CapabilityKeeper.ScopeToModule(icactlmoduletypes.ModuleName)
// Applications that wish to enforce statically created ScopedKeepers should call `Seal` after creating
// their scoped modules in `NewApp` with `ScopeToModule`
app.CapabilityKeeper.Seal()
Expand Down Expand Up @@ -529,7 +550,19 @@ func New(
transferStack = transfer.NewIBCModule(app.TransferKeeper)
transferStack = middleware.NewIBCConversionModule(transferStack, app.CronosKeeper)
transferStack = ibcfee.NewIBCMiddleware(transferStack, app.IBCFeeKeeper)
app.ICAControllerKeeper = icacontrollerkeeper.NewKeeper(
appCodec, keys[icacontrollertypes.StoreKey], app.GetSubspace(icacontrollertypes.SubModuleName),
app.IBCKeeper.ChannelKeeper, // may be replaced with middleware such as ics29 fee
app.IBCKeeper.ChannelKeeper, &app.IBCKeeper.PortKeeper,
scopedICAControllerKeeper, app.MsgServiceRouter(),
)
icaModule := ica.NewAppModule(&app.ICAControllerKeeper, nil)

app.ICAAuthKeeper = *icactlmodulekeeper.NewKeeper(appCodec,
app.GetSubspace(icactlmoduletypes.ModuleName), app.ICAControllerKeeper, scopedICAAuthKeeper)
icaAuthModule := icactlmodule.NewAppModule(appCodec, app.ICAAuthKeeper)
icaAuthIBCModule := icactlmodule.NewIBCModule(app.ICAAuthKeeper)
icaControllerIBCModule := icacontroller.NewIBCModule(app.ICAControllerKeeper, icaAuthIBCModule)
app.GovKeeper = govkeeper.NewKeeper(
appCodec, keys[govtypes.StoreKey], app.GetSubspace(govtypes.ModuleName), app.AccountKeeper, app.BankKeeper,
&stakingKeeper, govRouter, app.MsgServiceRouter(), govConfig,
Expand Down Expand Up @@ -564,6 +597,8 @@ func New(
// Create static IBC router, add transfer route, then set and seal it
ibcRouter := porttypes.NewRouter()
ibcRouter.AddRoute(ibctransfertypes.ModuleName, transferStack)
ibcRouter.AddRoute(icacontrollertypes.SubModuleName, icaControllerIBCModule)
ibcRouter.AddRoute(icactlmoduletypes.ModuleName, icaControllerIBCModule)
// this line is used by starport scaffolding # ibc/app/router
app.IBCKeeper.SetRouter(ibcRouter)

Expand Down Expand Up @@ -598,6 +633,8 @@ func New(
authzmodule.NewAppModule(appCodec, app.AuthzKeeper, app.AccountKeeper, app.BankKeeper, app.interfaceRegistry),
ibc.NewAppModule(app.IBCKeeper),
transferModule,
icaModule,
icaAuthModule,
feeModule,
evm.NewAppModule(app.EvmKeeper, app.AccountKeeper, evmS),
feemarket.NewAppModule(app.FeeMarketKeeper, feeMarketS),
Expand All @@ -616,6 +653,8 @@ func New(
evidencetypes.ModuleName, stakingtypes.ModuleName, ibchost.ModuleName,
ibctransfertypes.ModuleName,
ibcfeetypes.ModuleName,
icatypes.ModuleName,
icactlmoduletypes.ModuleName,
authtypes.ModuleName,
banktypes.ModuleName,
govtypes.ModuleName,
Expand All @@ -634,6 +673,8 @@ func New(
ibchost.ModuleName,
ibctransfertypes.ModuleName,
ibcfeetypes.ModuleName,
icatypes.ModuleName,
icactlmoduletypes.ModuleName,
capabilitytypes.ModuleName,
authtypes.ModuleName,
banktypes.ModuleName,
Expand Down Expand Up @@ -674,6 +715,8 @@ func New(
evidencetypes.ModuleName,
ibctransfertypes.ModuleName,
ibcfeetypes.ModuleName,
icatypes.ModuleName,
icactlmoduletypes.ModuleName,
authz.ModuleName,
feegrant.ModuleName,
paramstypes.ModuleName,
Expand Down Expand Up @@ -748,6 +791,25 @@ func New(
// upgrade.
app.setPostHandler()

planName := "v0.8.0"
app.UpgradeKeeper.SetUpgradeHandler(planName, func(ctx sdk.Context, _ upgradetypes.Plan, fromVM module.VersionMap) (module.VersionMap, error) {
return app.mm.RunMigrations(ctx, app.configurator, fromVM)
})

upgradeInfo, err := app.UpgradeKeeper.ReadUpgradeInfoFromDisk()
if err != nil {
panic(fmt.Sprintf("failed to read upgrade info from disk %s", err))
}

if upgradeInfo.Name == planName && !app.UpgradeKeeper.IsSkipHeight(upgradeInfo.Height) {
storeUpgrades := storetypes.StoreUpgrades{
Added: []string{icacontrollertypes.StoreKey},
}

// configure store loader that checks if version == upgradeHeight and applies store upgrades
app.SetStoreLoader(upgradetypes.UpgradeStoreLoader(upgradeInfo.Height, &storeUpgrades))
}

if loadLatest {
if err := app.LoadLatestVersion(); err != nil {
tmos.Exit(err.Error())
Expand All @@ -764,6 +826,8 @@ func New(

app.ScopedIBCKeeper = scopedIBCKeeper
app.ScopedTransferKeeper = scopedTransferKeeper
app.ScopedICAControllerKeeper = scopedICAControllerKeeper
app.ScopedICAAuthKeeper = scopedICAAuthKeeper
// this line is used by starport scaffolding # stargate/app/beforeInitReturn

return app
Expand Down Expand Up @@ -967,6 +1031,8 @@ func initParamsKeeper(appCodec codec.BinaryCodec, legacyAmino *codec.LegacyAmino
paramsKeeper.Subspace(crisistypes.ModuleName)
paramsKeeper.Subspace(ibctransfertypes.ModuleName)
paramsKeeper.Subspace(ibchost.ModuleName)
paramsKeeper.Subspace(icacontrollertypes.SubModuleName)
paramsKeeper.Subspace(icactlmoduletypes.ModuleName)
paramsKeeper.Subspace(evmtypes.ModuleName).WithKeyTable(evmtypes.ParamKeyTable()) //nolint: staticcheck
paramsKeeper.Subspace(feemarkettypes.ModuleName).WithKeyTable(feemarkettypes.ParamKeyTable())
if !skipGravity {
Expand Down
89 changes: 89 additions & 0 deletions integration_tests/test_ibc.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import base64
import hashlib

import pytest
Expand Down Expand Up @@ -433,3 +434,91 @@ def check_contract_balance_change():
def ibc_denom(channel, denom):
h = hashlib.sha256(f"transfer/{channel}/{denom}".encode()).hexdigest().upper()
return f"ibc/{h}"


def test_ica(ibc, tmp_path):
connid = "connection-0"
cli_host = ibc.chainmain.cosmos_cli()
cli_controller = ibc.cronos.cosmos_cli()

print("register ica account")
rsp = cli_controller.ica_register_account(
connid, from_="signer2", gas="400000", fees="100000000basetcro"
)
assert rsp["code"] == 0, rsp["raw_log"]
port_id, channel_id = next(
(
base64.b64decode(evt["attributes"][0]["value"].encode()).decode(),
base64.b64decode(evt["attributes"][1]["value"].encode()).decode(),
)
for evt in rsp["events"]
if evt["type"] == "channel_open_init"
)
print("port-id", port_id, "channel-id", channel_id)

print("wait for ica channel ready")

def check_channel_ready():
channels = cli_controller.ibc_query_channels(connid)["channels"]
try:
state = next(
channel["state"]
for channel in channels
if channel["channel_id"] == channel_id
)
except StopIteration:
return False
return state == "STATE_OPEN"

wait_for_fn("channel ready", check_channel_ready)

print("query ica account")
ica_address = cli_controller.ica_query_account(
connid, cli_controller.address("signer2")
)["interchainAccountAddress"]
print("ica address", ica_address)

# initial balance of interchain account should be zero
assert cli_host.balance(ica_address) == 0

# send some funds to interchain account
rsp = cli_host.transfer("signer2", ica_address, "1cro", gas_prices="1000000basecro")
assert rsp["code"] == 0, rsp["raw_log"]
wait_for_new_blocks(cli_host, 1)

# check if the funds are received in interchain account
assert cli_host.balance(ica_address, denom="basecro") == 100000000

# generate a transaction to send to host chain
generated_tx = tmp_path / "generated_tx.txt"
generated_tx_msg = cli_host.transfer(
ica_address, cli_host.address("signer2"), "0.5cro", generate_only=True
)

print(generated_tx_msg)
generated_tx.write_text(json.dumps(generated_tx_msg))

num_txs = len(cli_host.query_all_txs(ica_address)["txs"])

# submit transaction on host chain on behalf of interchain account
rsp = cli_controller.ica_submit_tx(
connid,
generated_tx,
from_="signer2",
)
assert rsp["code"] == 0, rsp["raw_log"]
packet_seq = next(
int(base64.b64decode(evt["attributes"][4]["value"].encode()))
for evt in rsp["events"]
if evt["type"] == "send_packet"
)
print("packet sequence", packet_seq)

def check_ica_tx():
return len(cli_host.query_all_txs(ica_address)["txs"]) > num_txs

print("wait for ica tx arrive")
wait_for_fn("ica transfer tx", check_ica_tx)

# check if the funds are reduced in interchain account
assert cli_host.balance(ica_address, denom="basecro") == 50000000
3 changes: 3 additions & 0 deletions nix/chainmain.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{ pkgs ? import ./default.nix { }, sources ? import ./sources.nix }:
(import sources.chain-main { }).chain-maind

13 changes: 13 additions & 0 deletions proto/icactl/v1/genesis.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
syntax = "proto3";
package cronos.icactl.v1;

import "gogoproto/gogo.proto";
import "icactl/v1/params.proto";

option go_package = "github.com/crypto-org-chain/cronos/v2/x/icactl/types";

// GenesisState defines the icactl module's genesis state.
message GenesisState {
// params defines the genesis parameters
Params params = 1 [ (gogoproto.nullable) = false ];
}
20 changes: 20 additions & 0 deletions proto/icactl/v1/params.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
syntax = "proto3";
package cronos.icactl.v1;

import "google/protobuf/duration.proto";
import "gogoproto/gogo.proto";

option go_package = "github.com/crypto-org-chain/cronos/v2/x/icactl/types";

// Params defines the parameters for the module.
message Params {
option (gogoproto.goproto_stringer) = false;

// minTimeoutDuration defines the minimum value of packet timeout when
// submitting transactions to host chain on behalf of interchain account
google.protobuf.Duration minTimeoutDuration = 1 [
(gogoproto.moretags) = "yaml:\"min_timeout_duration\"",
(gogoproto.stdduration) = true,
(gogoproto.nullable) = false
];
}
Loading

0 comments on commit 5810f9c

Please sign in to comment.