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

Problem: ibc channel upgrade related methods are not supported #1612

Merged
merged 3 commits into from
Sep 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
* [#1600](https://github.com/crypto-org-chain/cronos/pull/1600) Update ethermint to avoid unnecessary block result in header related api call.
* [#1606](https://github.com/crypto-org-chain/cronos/pull/1606) Fix pebbledb support.
* [#1610](https://github.com/crypto-org-chain/cronos/pull/1610) Sync e2ee module with v1.3.x branch.
* [#1612](https://github.com/crypto-org-chain/cronos/pull/1612) Support ibc channel upgrade related methods.

### Bug Fixes

Expand Down
44 changes: 41 additions & 3 deletions integration_tests/cosmoscli.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
from dateutil.parser import isoparse
from pystarport.utils import build_cli_args_safe, format_doc_string, interact

from .utils import get_sync_info
from .utils import CRONOS_ADDRESS_PREFIX, get_sync_info

# the default initial base fee used by integration tests
DEFAULT_GAS_PRICE = "100000000000basetcro"
Expand All @@ -34,14 +34,14 @@ class ModuleAccount(enum.Enum):
@format_doc_string(
options=",".join(v.value for v in ModuleAccount.__members__.values())
)
def module_address(name):
def module_address(name, prefix=CRONOS_ADDRESS_PREFIX):
"""
get address of module accounts

:param name: name of module account, values: {options}
"""
data = hashlib.sha256(ModuleAccount(name).value.encode()).digest()[:20]
return bech32.bech32_encode("cro", bech32.convertbits(data, 8, 5))
return bech32.bech32_encode(prefix, bech32.convertbits(data, 8, 5))


class ChainCommand:
Expand Down Expand Up @@ -1238,6 +1238,27 @@ def ibc_recover_client(self, proposal, **kwargs):
rsp = self.event_query_tx_for(rsp["txhash"])
return rsp

def ibc_upgrade_channels(self, version, from_addr, **kwargs):
kwargs.setdefault("gas_prices", DEFAULT_GAS_PRICE)
kwargs.setdefault("gas", 600000)
return json.loads(
self.raw(
"tx",
"ibc",
"channel",
"upgrade-channels",
json.dumps(version),
"-y",
"--json",
from_=from_addr,
keyring_backend="test",
chain_id=self.chain_id,
home=self.data_dir,
stderr=subprocess.DEVNULL,
**kwargs,
)
)

def submit_gov_proposal(self, proposal, **kwargs):
default_kwargs = self.get_default_kwargs()
kwargs.setdefault("broadcast_mode", "sync")
Expand Down Expand Up @@ -1428,6 +1449,23 @@ def ibc_query_channels(self, connid, **kwargs):
)
)

def ibc_query_channel(self, port_id, channel_id, **kwargs):
default_kwargs = {
"node": self.node_rpc,
"output": "json",
}
return json.loads(
self.raw(
"q",
"ibc",
"channel",
"end",
port_id,
channel_id,
**(default_kwargs | kwargs),
)
)

mmsqe marked this conversation as resolved.
Show resolved Hide resolved
def ibc_query_ack(self, port_id, channel_id, packet_seq, **kwargs):
default_kwargs = {
"node": self.node_rpc,
Expand Down
29 changes: 15 additions & 14 deletions integration_tests/ibc_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -201,18 +201,7 @@ def prepare_network(
call_rly_cmd(path, connection_only, version)

if incentivized:
# register fee payee
src_chain = cronos.cosmos_cli()
dst_chain = chainmain.cosmos_cli()
rsp = dst_chain.register_counterparty_payee(
"transfer",
"channel-0",
dst_chain.address("relayer"),
src_chain.address("signer1"),
from_="relayer",
fees="100000000basecro",
)
assert rsp["code"] == 0, rsp["raw_log"]
register_fee_payee(cronos.cosmos_cli(), chainmain.cosmos_cli())

port = None
if is_relay:
Expand All @@ -226,6 +215,18 @@ def prepare_network(
wait_for_port(port)


def register_fee_payee(src_chain, dst_chain):
rsp = dst_chain.register_counterparty_payee(
"transfer",
"channel-0",
dst_chain.address("relayer"),
src_chain.address("signer1"),
from_="relayer",
fees="100000000basecro",
)
assert rsp["code"] == 0, rsp["raw_log"]

mmsqe marked this conversation as resolved.
Show resolved Hide resolved

def assert_ready(ibc):
# wait for hermes
output = subprocess.getoutput(
Expand Down Expand Up @@ -772,7 +773,7 @@ def register_acc(cli, connid, ordering=ChannelOrder.ORDERED.value, signer="signe
version=v,
ordering=ordering,
)
_, channel_id = assert_channel_open_init(rsp)
port_id, channel_id = assert_channel_open_init(rsp)
wait_for_check_channel_ready(cli, connid, channel_id)

print("query ica account")
Expand All @@ -781,7 +782,7 @@ def register_acc(cli, connid, ordering=ChannelOrder.ORDERED.value, signer="signe
cli.address(signer),
)["address"]
print("ica address", ica_address, "channel_id", channel_id)
return ica_address, channel_id
return ica_address, port_id, channel_id


def funds_ica(cli, adr, signer="signer2"):
Expand Down
41 changes: 38 additions & 3 deletions integration_tests/test_ibc.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import json

import pytest

from .cosmoscli import module_address
from .ibc_utils import (
RATIO,
assert_ready,
Expand All @@ -10,10 +13,13 @@
ibc_incentivized_transfer,
ibc_transfer,
prepare_network,
register_fee_payee,
wait_for_check_channel_ready,
)
from .utils import (
ADDRS,
CONTRACTS,
approve_proposal,
deploy_contract,
parse_events_rpc,
send_transaction,
Expand Down Expand Up @@ -58,10 +64,39 @@ def test_ibc_transfer(ibc):
assert not dup, f"duplicate {dup} in {event['type']}"


def test_ibc_incentivized_transfer(ibc):
def test_ibc_incentivized_transfer(ibc, tmp_path):
if not ibc.incentivized:
# this test case only works for incentivized channel.
return
# upgrade to incentivized
src_chain = ibc.cronos.cosmos_cli()
dst_chain = ibc.chainmain.cosmos_cli()
version = {"fee_version": "ics29-1", "app_version": "ics20-1"}
community = "community"
authority = module_address("gov")
connid = "connection-0"
channel_id = "channel-0"
deposit = "1basetcro"
proposal_src = src_chain.ibc_upgrade_channels(
version,
community,
deposit=deposit,
title="channel-upgrade-title",
summary="summary",
port_pattern="transfer",
channel_ids=channel_id,
)
proposal_src["deposit"] = deposit
proposal_src["proposer"] = authority
proposal_src["messages"][0]["signer"] = authority
proposal = tmp_path / "proposal.json"
proposal.write_text(json.dumps(proposal_src))
rsp = src_chain.submit_gov_proposal(proposal, from_=community)
assert rsp["code"] == 0, rsp["raw_log"]
mmsqe marked this conversation as resolved.
Show resolved Hide resolved
approve_proposal(ibc.cronos, rsp["events"])
wait_for_check_channel_ready(
src_chain, connid, channel_id, "STATE_FLUSHCOMPLETE"
)
wait_for_check_channel_ready(src_chain, connid, channel_id)
mmsqe marked this conversation as resolved.
Show resolved Hide resolved
register_fee_payee(src_chain, dst_chain)
ibc_incentivized_transfer(ibc)


Expand Down
45 changes: 41 additions & 4 deletions integration_tests/test_ica.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import pytest
from pystarport import cluster

from .cosmoscli import module_address
from .ibc_utils import (
ChannelOrder,
Status,
Expand All @@ -17,7 +18,7 @@
wait_for_check_tx,
wait_for_status_change,
)
from .utils import CONTRACTS, wait_for_fn
from .utils import CONTRACTS, approve_proposal, wait_for_fn

pytestmark = pytest.mark.ica

Expand All @@ -39,12 +40,12 @@ def ibc(request, tmp_path_factory):
@pytest.mark.parametrize(
"order", [ChannelOrder.ORDERED.value, ChannelOrder.UNORDERED.value]
)
def test_ica(ibc, order):
def test_ica(ibc, order, tmp_path):
signer = "signer2" if order == ChannelOrder.ORDERED.value else "community"
connid = "connection-0"
cli_host = ibc.chainmain.cosmos_cli()
cli_controller = ibc.cronos.cosmos_cli()
ica_address, channel_id = register_acc(
ica_address, _, channel_id = register_acc(
cli_controller, connid, ordering=order, signer=signer
)
balance = funds_ica(cli_host, ica_address, signer=signer)
Expand Down Expand Up @@ -118,9 +119,45 @@ def submit_msgs(msg_num, timeout_in_s=no_timeout, gas="200000"):
else:
wait_for_check_channel_ready(cli_controller, connid, channel_id, "STATE_CLOSED")
# reopen ica account after channel get closed
ica_address2, channel_id2 = register_acc(cli_controller, connid)
ica_address2, port_id2, channel_id2 = register_acc(cli_controller, connid)
assert ica_address2 == ica_address, ica_address2
assert channel_id2 != channel_id, channel_id2
# upgrade to unordered channel
channel = cli_controller.ibc_query_channel(port_id2, channel_id2)
version_data = json.loads(channel["channel"]["version"])
community = "community"
authority = module_address("gov")
deposit = "1basetcro"
proposal_src = cli_controller.ibc_upgrade_channels(
json.loads(version_data["app_version"]),
community,
deposit=deposit,
title="channel-upgrade-title",
summary="summary",
port_pattern=port_id2,
channel_ids=channel_id2,
)
proposal_src["deposit"] = deposit
proposal_src["proposer"] = authority
proposal_src["messages"][0]["signer"] = authority
mmsqe marked this conversation as resolved.
Show resolved Hide resolved
proposal_src["messages"][0]["fields"]["ordering"] = ChannelOrder.UNORDERED.value
mmsqe marked this conversation as resolved.
Show resolved Hide resolved
proposal = tmp_path / "proposal.json"
proposal.write_text(json.dumps(proposal_src))
rsp = cli_controller.submit_gov_proposal(proposal, from_=community)
assert rsp["code"] == 0, rsp["raw_log"]
approve_proposal(ibc.cronos, rsp["events"])
wait_for_check_channel_ready(
cli_controller, connid, channel_id2, "STATE_FLUSHCOMPLETE"
)
wait_for_check_channel_ready(cli_controller, connid, channel_id2)
# submit large txs to trigger close channel with small timeout for order channel
msg_num = 140
submit_msgs(msg_num, 0.005, "600000")
assert cli_host.balance(ica_address, denom=denom) == balance
with pytest.raises(AssertionError) as exc:
register_acc(cli_controller, connid)
assert "existing active channel" in str(exc.value)

# submit normal txs should work
msg_num = 2
submit_msgs(msg_num)
Expand Down
2 changes: 1 addition & 1 deletion integration_tests/test_ica_incentivized.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ def test_incentivized(ibc):
connid = "connection-0"
cli_host = ibc.chainmain.cosmos_cli()
cli_controller = ibc.cronos.cosmos_cli()
ica_address, channel_id = register_acc(cli_controller, connid)
ica_address, _, channel_id = register_acc(cli_controller, connid)
mmsqe marked this conversation as resolved.
Show resolved Hide resolved
relayer = cli_controller.address("signer1")
balance = funds_ica(cli_host, ica_address)
ibc.cronos.supervisorctl("stop", "relayer-demo")
Expand Down
45 changes: 45 additions & 0 deletions x/cronos/middleware/conversion_middleware.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
cronoskeeper "github.com/crypto-org-chain/cronos/v2/x/cronos/keeper"
)

var _ porttypes.UpgradableModule = (*IBCConversionModule)(nil)

// IBCConversionModule implements the ICS26 interface.
type IBCConversionModule struct {
app porttypes.IBCModule
Expand Down Expand Up @@ -228,3 +230,46 @@
denomTrace := transferTypes.ParseDenomTrace(prefixedDenom)
return denomTrace.IBCDenom()
}

// OnChanUpgradeInit implements the IBCModule interface
func (im IBCConversionModule) OnChanUpgradeInit(
ctx sdk.Context,
portID string,
channelID string,
proposedOrder channeltypes.Order,
proposedConnectionHops []string,
proposedVersion string,
) (string, error) {
cbs, ok := im.app.(porttypes.UpgradableModule)
if !ok {
return "", errors.Wrap(porttypes.ErrInvalidRoute, "upgrade route not found to module in application callstack")

Check warning on line 245 in x/cronos/middleware/conversion_middleware.go

View check run for this annotation

Codecov / codecov/patch

x/cronos/middleware/conversion_middleware.go#L242-L245

Added lines #L242 - L245 were not covered by tests
}
return cbs.OnChanUpgradeInit(ctx, portID, channelID, proposedOrder, proposedConnectionHops, proposedVersion)

Check warning on line 247 in x/cronos/middleware/conversion_middleware.go

View check run for this annotation

Codecov / codecov/patch

x/cronos/middleware/conversion_middleware.go#L247

Added line #L247 was not covered by tests
}

// OnChanUpgradeAck implements the IBCModule interface
func (im IBCConversionModule) OnChanUpgradeAck(ctx sdk.Context, portID, channelID, counterpartyVersion string) error {
cbs, ok := im.app.(porttypes.UpgradableModule)
if !ok {
return errors.Wrap(porttypes.ErrInvalidRoute, "upgrade route not found to module in application callstack")

Check warning on line 254 in x/cronos/middleware/conversion_middleware.go

View check run for this annotation

Codecov / codecov/patch

x/cronos/middleware/conversion_middleware.go#L251-L254

Added lines #L251 - L254 were not covered by tests
}
return cbs.OnChanUpgradeAck(ctx, portID, channelID, counterpartyVersion)

Check warning on line 256 in x/cronos/middleware/conversion_middleware.go

View check run for this annotation

Codecov / codecov/patch

x/cronos/middleware/conversion_middleware.go#L256

Added line #L256 was not covered by tests
}

// OnChanUpgradeOpen implements the IBCModule interface
func (im IBCConversionModule) OnChanUpgradeOpen(ctx sdk.Context, portID, channelID string, proposedOrder channeltypes.Order, proposedConnectionHops []string, proposedVersion string) {
cbs, ok := im.app.(porttypes.UpgradableModule)
if !ok {
panic(errors.Wrap(porttypes.ErrInvalidRoute, "upgrade route not found to module in application callstack"))

Check warning on line 263 in x/cronos/middleware/conversion_middleware.go

View check run for this annotation

Codecov / codecov/patch

x/cronos/middleware/conversion_middleware.go#L260-L263

Added lines #L260 - L263 were not covered by tests
}
cbs.OnChanUpgradeOpen(ctx, portID, channelID, proposedOrder, proposedConnectionHops, proposedVersion)

Check warning on line 265 in x/cronos/middleware/conversion_middleware.go

View check run for this annotation

Codecov / codecov/patch

x/cronos/middleware/conversion_middleware.go#L265

Added line #L265 was not covered by tests
}
mmsqe marked this conversation as resolved.
Show resolved Hide resolved

// OnChanUpgradeTry implement s the IBCModule interface
func (im IBCConversionModule) OnChanUpgradeTry(ctx sdk.Context, portID, channelID string, proposedOrder channeltypes.Order, proposedConnectionHops []string, counterpartyVersion string) (string, error) {
cbs, ok := im.app.(porttypes.UpgradableModule)
if !ok {
return "", errors.Wrap(porttypes.ErrInvalidRoute, "upgrade route not found to module in application callstack")

Check warning on line 272 in x/cronos/middleware/conversion_middleware.go

View check run for this annotation

Codecov / codecov/patch

x/cronos/middleware/conversion_middleware.go#L269-L272

Added lines #L269 - L272 were not covered by tests
}
return cbs.OnChanUpgradeTry(ctx, portID, channelID, proposedOrder, proposedConnectionHops, counterpartyVersion)

Check warning on line 274 in x/cronos/middleware/conversion_middleware.go

View check run for this annotation

Codecov / codecov/patch

x/cronos/middleware/conversion_middleware.go#L274

Added line #L274 was not covered by tests
}
mmsqe marked this conversation as resolved.
Show resolved Hide resolved
Loading