Skip to content

Commit d575f3b

Browse files
mmsqeyihuang
andauthored
Problem: ibc refund is not tested in integration test (#613)
* add ibc timeout case * test refund * configurable ibc timeout height * revert covert for timeout introduced from cdcfda1 * fix for nonSource * fix isort under nix * fix parse trace for refund * test refund on ack err * Revert "configurable ibc timeout height" This reverts commit 1ba6e7a. * align pattern * revert debug * rename test * replace try finally with yield from for more info, https://stackoverflow.com/questions/9708902/in-practice-what-are-the-main-uses-for-the-yield-from-syntax-in-python-3-3 Co-authored-by: yihuang <huang@crypto.com>
1 parent 2d5fca8 commit d575f3b

File tree

6 files changed

+254
-130
lines changed

6 files changed

+254
-130
lines changed

integration_tests/configs/ibc.jsonnet

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,9 @@ config {
8484
},
8585
},
8686
relayer: {
87+
global: {
88+
strategy: 'all',
89+
},
8790
rest: {
8891
enabled: true,
8992
host: '127.0.0.1',
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
local ibc = import 'ibc.jsonnet';
2+
3+
ibc {
4+
'cronos_777-1'+: {
5+
genesis+: {
6+
app_state+: {
7+
cronos+: {
8+
params+: {
9+
ibc_timeout: 0,
10+
},
11+
},
12+
},
13+
},
14+
},
15+
}

integration_tests/ibc_utils.py

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
import json
2+
import subprocess
3+
from pathlib import Path
4+
from typing import NamedTuple
5+
6+
from pystarport import ports
7+
8+
from .network import Chainmain, Cronos, Hermes, setup_custom_cronos
9+
from .utils import ADDRS, eth_to_bech32, supervisorctl, wait_for_port
10+
11+
RATIO = 10**10
12+
13+
14+
class IBCNetwork(NamedTuple):
15+
cronos: Cronos
16+
chainmain: Chainmain
17+
hermes: Hermes
18+
19+
20+
def prepare_network(tmp_path, file):
21+
file = f"configs/{file}.jsonnet"
22+
gen = setup_custom_cronos(tmp_path, 26700, Path(__file__).parent / file)
23+
cronos = next(gen)
24+
chainmain = Chainmain(cronos.base_dir.parent / "chainmain-1")
25+
hermes = Hermes(cronos.base_dir.parent / "relayer.toml")
26+
# wait for grpc ready
27+
wait_for_port(ports.grpc_port(chainmain.base_port(0))) # chainmain grpc
28+
wait_for_port(ports.grpc_port(cronos.base_port(0))) # cronos grpc
29+
subprocess.check_call(
30+
[
31+
"hermes",
32+
"-c",
33+
hermes.configpath,
34+
"create",
35+
"channel",
36+
"cronos_777-1",
37+
"chainmain-1",
38+
"--port-a",
39+
"transfer",
40+
"--port-b",
41+
"transfer",
42+
]
43+
)
44+
supervisorctl(cronos.base_dir / "../tasks.ini", "start", "relayer-demo")
45+
wait_for_port(hermes.port)
46+
yield IBCNetwork(cronos, chainmain, hermes)
47+
48+
49+
def assert_ready(ibc):
50+
# wait for hermes
51+
output = subprocess.getoutput(
52+
f"curl -s -X GET 'http://127.0.0.1:{ibc.hermes.port}/state' | jq"
53+
)
54+
assert json.loads(output)["status"] == "success"
55+
56+
57+
def prepare(ibc):
58+
assert_ready(ibc)
59+
# chainmain-1 -> cronos_777-1
60+
my_ibc0 = "chainmain-1"
61+
my_ibc1 = "cronos_777-1"
62+
my_channel = "channel-0"
63+
dst_addr = eth_to_bech32(ADDRS["signer2"])
64+
src_amount = 10
65+
src_denom = "basecro"
66+
# dstchainid srcchainid srcportid srchannelid
67+
cmd = (
68+
f"hermes -c {ibc.hermes.configpath} tx raw ft-transfer "
69+
f"{my_ibc1} {my_ibc0} transfer {my_channel} {src_amount} "
70+
f"-o 1000 -n 1 -d {src_denom} -r {dst_addr} -k relayer"
71+
)
72+
subprocess.run(cmd, check=True, shell=True)
73+
return src_amount
74+
75+
76+
def get_balance(chain, addr, denom):
77+
balance = chain.cosmos_cli().balance(addr, denom)
78+
print("balance", balance, addr, denom)
79+
return balance

integration_tests/test_ibc.py

Lines changed: 80 additions & 116 deletions
Original file line numberDiff line numberDiff line change
@@ -1,182 +1,150 @@
11
import base64
22
import json
3-
import subprocess
4-
from pathlib import Path
5-
from typing import NamedTuple
63

74
import pytest
8-
from pystarport import ports
95

10-
from .network import Chainmain, Cronos, Hermes, setup_custom_cronos
6+
from .ibc_utils import RATIO, assert_ready, get_balance, prepare, prepare_network
117
from .utils import (
128
ADDRS,
139
CONTRACTS,
1410
deploy_contract,
1511
eth_to_bech32,
1612
send_transaction,
17-
supervisorctl,
1813
wait_for_fn,
1914
wait_for_new_blocks,
20-
wait_for_port,
2115
)
2216

2317

24-
class IBCNetwork(NamedTuple):
25-
cronos: Cronos
26-
chainmain: Chainmain
27-
hermes: Hermes
28-
29-
3018
@pytest.fixture(scope="module")
3119
def ibc(request, tmp_path_factory):
32-
"start-cronos"
33-
path = tmp_path_factory.mktemp("ibc")
34-
gen = setup_custom_cronos(
35-
path, 26700, Path(__file__).parent / "configs/ibc.jsonnet"
36-
)
37-
cronos = next(gen)
38-
try:
39-
chainmain = Chainmain(cronos.base_dir.parent / "chainmain-1")
40-
hermes = Hermes(cronos.base_dir.parent / "relayer.toml")
41-
# wait for grpc ready
42-
wait_for_port(ports.grpc_port(chainmain.base_port(0))) # chainmain grpc
43-
wait_for_port(ports.grpc_port(cronos.base_port(0))) # cronos grpc
44-
subprocess.check_call(
45-
[
46-
"hermes",
47-
"-c",
48-
hermes.configpath,
49-
"create",
50-
"channel",
51-
"cronos_777-1",
52-
"chainmain-1",
53-
"--port-a",
54-
"transfer",
55-
"--port-b",
56-
"transfer",
57-
]
58-
)
59-
supervisorctl(cronos.base_dir / "../tasks.ini", "start", "relayer-demo")
60-
wait_for_port(hermes.port)
61-
yield IBCNetwork(cronos, chainmain, hermes)
62-
finally:
63-
try:
64-
next(gen)
65-
except StopIteration:
66-
pass
67-
68-
69-
def get_balance(chain, addr, denom):
70-
return chain.cosmos_cli().balance(addr, denom)
20+
"prepare-network"
21+
name = "ibc"
22+
path = tmp_path_factory.mktemp(name)
23+
network = prepare_network(path, name)
24+
yield from network
7125

7226

7327
def get_balances(chain, addr):
7428
return chain.cosmos_cli().balances(addr)
7529

7630

7731
def test_ibc(ibc):
78-
"test sending basecro from crypto-org chain to cronos"
79-
# wait for hermes
80-
output = subprocess.getoutput(
81-
f"curl -s -X GET 'http://127.0.0.1:{ibc.hermes.port}/state' | jq"
82-
)
83-
assert json.loads(output)["status"] == "success"
84-
85-
my_ibc0 = "chainmain-1"
86-
my_ibc1 = "cronos_777-1"
87-
my_channel = "channel-0"
88-
my_config = ibc.hermes.configpath
89-
# signer2
90-
coin_receiver = eth_to_bech32(ADDRS["signer2"])
91-
src_amount = 10
92-
dst_amount = src_amount * (10**10) # the decimal places difference
93-
src_denom = "basecro"
32+
src_amount = prepare(ibc)
33+
dst_amount = src_amount * RATIO # the decimal places difference
9434
dst_denom = "basetcro"
95-
# dstchainid srcchainid srcportid srchannelid
96-
# chainmain-1 -> cronos_777-1
97-
cmd = (
98-
f"hermes -c {my_config} tx raw ft-transfer "
99-
f"{my_ibc1} {my_ibc0} transfer {my_channel} {src_amount} "
100-
f"-o 1000 -n 1 -d {src_denom} -r {coin_receiver} -k relayer"
101-
)
102-
subprocess.run(cmd, check=True, shell=True)
103-
dstaddr = f"{coin_receiver}"
104-
olddstbalance = get_balance(ibc.cronos, dstaddr, dst_denom)
105-
newdstbalance = 0
35+
dst_addr = eth_to_bech32(ADDRS["signer2"])
36+
old_dst_balance = get_balance(ibc.cronos, dst_addr, dst_denom)
37+
38+
new_dst_balance = 0
10639

10740
def check_balance_change():
108-
nonlocal newdstbalance
109-
newdstbalance = get_balance(ibc.cronos, dstaddr, dst_denom)
110-
return newdstbalance != olddstbalance
41+
nonlocal new_dst_balance
42+
new_dst_balance = get_balance(ibc.cronos, dst_addr, dst_denom)
43+
return new_dst_balance != old_dst_balance
11144

112-
wait_for_fn("check balance change", check_balance_change)
113-
expectedbalance = olddstbalance + dst_amount
114-
assert expectedbalance == newdstbalance
45+
wait_for_fn("balance change", check_balance_change)
46+
assert old_dst_balance + dst_amount == new_dst_balance
11547

11648

11749
def test_cronos_transfer_tokens(ibc):
11850
"""
11951
test sending basetcro from cronos to crypto-org-chain using cli transfer_tokens.
12052
depends on `test_ibc` to send the original coins.
12153
"""
122-
output = subprocess.getoutput(
123-
f"curl -s -X GET 'http://127.0.0.1:{ibc.hermes.port}/state' | jq"
124-
)
125-
assert json.loads(output)["status"] == "success"
126-
127-
coin_receiver = ibc.chainmain.cosmos_cli().address("signer2")
54+
assert_ready(ibc)
55+
dst_addr = ibc.chainmain.cosmos_cli().address("signer2")
12856
dst_amount = 2
129-
src_amount = dst_amount * (10**10) # the decimal places difference
57+
dst_denom = "basecro"
58+
cli = ibc.cronos.cosmos_cli()
59+
src_amount = dst_amount * RATIO # the decimal places difference
60+
src_addr = cli.address("signer2")
61+
src_denom = "basetcro"
13062

13163
# case 1: use cronos cli
132-
oldbalance = get_balance(ibc.chainmain, coin_receiver, "basecro")
64+
old_src_balance = get_balance(ibc.cronos, src_addr, src_denom)
65+
old_dst_balance = get_balance(ibc.chainmain, dst_addr, dst_denom)
66+
rsp = cli.transfer_tokens(
67+
src_addr,
68+
dst_addr,
69+
f"{src_amount}{src_denom}",
70+
)
71+
assert rsp["code"] == 0, rsp["raw_log"]
72+
73+
new_dst_balance = 0
74+
75+
def check_balance_change():
76+
nonlocal new_dst_balance
77+
new_dst_balance = get_balance(ibc.chainmain, dst_addr, dst_denom)
78+
return old_dst_balance != new_dst_balance
79+
80+
wait_for_fn("balance change", check_balance_change)
81+
assert old_dst_balance + dst_amount == new_dst_balance
82+
new_src_balance = get_balance(ibc.cronos, src_addr, src_denom)
83+
assert old_src_balance - src_amount == new_src_balance
84+
85+
86+
def test_cronos_transfer_tokens_acknowledgement_error(ibc):
87+
"""
88+
test sending basetcro from cronos to crypto-org-chain using cli transfer_tokens
89+
with invalid receiver for acknowledgement error.
90+
depends on `test_ibc` to send the original coins.
91+
"""
92+
assert_ready(ibc)
93+
dst_addr = "invalid_address"
94+
dst_amount = 2
13395
cli = ibc.cronos.cosmos_cli()
96+
src_amount = dst_amount * RATIO # the decimal places difference
97+
src_addr = cli.address("signer2")
98+
src_denom = "basetcro"
99+
100+
old_src_balance = get_balance(ibc.cronos, src_addr, src_denom)
134101
rsp = cli.transfer_tokens(
135-
cli.address("signer2"),
136-
coin_receiver,
137-
f"{src_amount}basetcro",
102+
src_addr,
103+
dst_addr,
104+
f"{src_amount}{src_denom}",
138105
)
139106
assert rsp["code"] == 0, rsp["raw_log"]
140107

141-
newbalance = 0
108+
new_src_balance = 0
142109

143110
def check_balance_change():
144-
nonlocal newbalance
145-
newbalance = get_balance(ibc.chainmain, coin_receiver, "basecro")
146-
return oldbalance != newbalance
111+
nonlocal new_src_balance
112+
new_src_balance = get_balance(ibc.cronos, src_addr, src_denom)
113+
return old_src_balance == new_src_balance
147114

148-
wait_for_fn("check balance change", check_balance_change)
149-
assert oldbalance + dst_amount == newbalance
115+
wait_for_fn("balance no change", check_balance_change)
116+
new_src_balance = get_balance(ibc.cronos, src_addr, src_denom)
150117

151118

152119
def test_cro_bridge_contract(ibc):
153120
"""
154121
test sending basetcro from cronos to crypto-org-chain using CroBridge contract.
155122
depends on `test_ibc` to send the original coins.
156123
"""
157-
coin_receiver = ibc.chainmain.cosmos_cli().address("signer2")
124+
dst_addr = ibc.chainmain.cosmos_cli().address("signer2")
158125
dst_amount = 2
159-
src_amount = dst_amount * (10**10) # the decimal places difference
160-
oldbalance = get_balance(ibc.chainmain, coin_receiver, "basecro")
126+
dst_denom = "basecro"
127+
src_amount = dst_amount * RATIO # the decimal places difference
128+
old_dst_balance = get_balance(ibc.chainmain, dst_addr, dst_denom)
161129

162130
# case 2: use CroBridge contract
163131
w3 = ibc.cronos.w3
164132
contract = deploy_contract(w3, CONTRACTS["CroBridge"])
165-
tx = contract.functions.send_cro_to_crypto_org(coin_receiver).buildTransaction(
133+
tx = contract.functions.send_cro_to_crypto_org(dst_addr).buildTransaction(
166134
{"from": ADDRS["signer2"], "value": src_amount}
167135
)
168136
receipt = send_transaction(w3, tx)
169137
assert receipt.status == 1
170138

171-
newbalance = 0
139+
new_dst_balance = 0
172140

173141
def check_balance_change():
174-
nonlocal newbalance
175-
newbalance = get_balance(ibc.chainmain, coin_receiver, "basecro")
176-
return oldbalance != newbalance
142+
nonlocal new_dst_balance
143+
new_dst_balance = get_balance(ibc.chainmain, dst_addr, dst_denom)
144+
return old_dst_balance != new_dst_balance
177145

178146
wait_for_fn("check balance change", check_balance_change)
179-
assert oldbalance + dst_amount == newbalance
147+
assert old_dst_balance + dst_amount == new_dst_balance
180148

181149

182150
def test_ica(ibc, tmp_path):
@@ -271,11 +239,7 @@ def test_cronos_transfer_source_tokens(ibc):
271239
"""
272240
test sending crc20 tokens originated from cronos to crypto-org-chain
273241
"""
274-
output = subprocess.getoutput(
275-
f"curl -s -X GET 'http://127.0.0.1:{ibc.hermes.port}/state' | jq"
276-
)
277-
assert json.loads(output)["status"] == "success"
278-
242+
assert_ready(ibc)
279243
# deploy crc21 contract
280244
w3 = ibc.cronos.w3
281245
contract = deploy_contract(w3, CONTRACTS["TestERC21Source"])

0 commit comments

Comments
 (0)