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: ica packet callback doesn't contain channel detail #1235

Merged
merged 13 commits into from
Nov 29, 2023
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
### State Machine Breaking

- [#1232](https://github.com/crypto-org-chain/cronos/pull/1232) Adjust require gas in relayer precompile to be closed with actual consumed.
- [#1235](https://github.com/crypto-org-chain/cronos/pull/1235) Add channel detail in ica packet callback.

### Improvements

Expand Down
8 changes: 5 additions & 3 deletions app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -637,15 +637,17 @@ func New(
}
app.StakingKeeper.SetHooks(stakingtypes.NewMultiStakingHooks(hooks...))

app.ICAAuthKeeper = *icaauthkeeper.NewKeeper(appCodec, keys[icaauthtypes.StoreKey], keys[icaauthtypes.MemStoreKey], app.ICAControllerKeeper, scopedICAAuthKeeper)
icaAuthModule := icaauth.NewAppModule(appCodec, app.ICAAuthKeeper)
app.ICAAuthKeeper = *icaauthkeeper.NewKeeper(appCodec, keys[icaauthtypes.StoreKey], keys[icaauthtypes.MemStoreKey], app.ICAControllerKeeper, scopedICAAuthKeeper, scopedICAControllerKeeper)
icaAuthIBCModule := icaauth.NewIBCModule(app.ICAAuthKeeper)

var icaControllerStack porttypes.IBCModule
icaControllerStack = icacontroller.NewIBCMiddleware(icaAuthIBCModule, app.ICAControllerKeeper)
icaControllerStack = ibcfee.NewIBCMiddleware(icaControllerStack, app.IBCFeeKeeper)
// Since the callbacks middleware itself is an ics4wrapper, it needs to be passed to the ica controller keeper
app.ICAControllerKeeper.WithICS4Wrapper(icaControllerStack.(porttypes.Middleware))
ics4Wrapper := icaControllerStack.(porttypes.Middleware)
app.ICAControllerKeeper.WithICS4Wrapper(ics4Wrapper)
app.ICAAuthKeeper.WithICS4Wrapper(ics4Wrapper)
icaAuthModule := icaauth.NewAppModule(appCodec, app.ICAAuthKeeper, ics4Wrapper)
// we don't limit gas usage here, because the cronos keeper will use network parameter to control it.
icaControllerStack = ibccallbacks.NewIBCMiddleware(icaControllerStack, app.IBCFeeKeeper, app.CronosKeeper, math.MaxUint64)

Expand Down
14 changes: 9 additions & 5 deletions integration_tests/contracts/contracts/TestICA.sol
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ contract TestICA {
SUCCESS,
FAIL
}
mapping (uint64 => Status) public statusMap;
event OnPacketResult(uint64 seq, Status status);
mapping (string => mapping (uint64 => Status)) public statusMap;
event OnPacketResult(string indexed packetSrcChannel, uint64 seq, Status status);

function encodeRegister(string memory connectionID, string memory version) internal view returns (bytes memory) {
return abi.encodeWithSignature(
Expand Down Expand Up @@ -102,15 +102,19 @@ contract TestICA {
return lastSeq;
}

function onPacketResultCallback(uint64 seq, bool ack) external payable returns (bool) {
function getStatus(string calldata packetSrcChannel, uint64 seq) public view returns (Status) {
return statusMap[packetSrcChannel][seq];
}

function onPacketResultCallback(string calldata packetSrcChannel, uint64 seq, bool ack) external payable returns (bool) {
// To prevent called by arbitrary user
require(msg.sender == module_address);
Status status = Status.FAIL;
if (ack) {
status = Status.SUCCESS;
}
statusMap[seq] = status;
emit OnPacketResult(seq, status);
statusMap[packetSrcChannel][seq] = status;
emit OnPacketResult(packetSrcChannel, seq, status);
return true;
}
}
69 changes: 46 additions & 23 deletions integration_tests/test_ica_precompile.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from enum import IntEnum

import pytest
from eth_utils import keccak
from pystarport import cluster
from web3.datastructures import AttributeDict

Expand Down Expand Up @@ -79,6 +80,7 @@ def submit_msgs(
amount=amt,
need_wait=True,
msg_num=2,
channel_id="",
mmsqe marked this conversation as resolved.
Show resolved Hide resolved
):
cli_host = ibc.chainmain.cosmos_cli()
cli_controller = ibc.cronos.cosmos_cli()
Expand Down Expand Up @@ -118,7 +120,12 @@ def submit_msgs(
else:
logs = event.getLogs()
assert len(logs) > 0
assert logs[0].args == AttributeDict({"seq": expected_seq})
assert logs[0].args == AttributeDict(
{
"packetSrcChannel": keccak(text=channel_id),
"seq": expected_seq,
}
)
if need_wait:
wait_for_check_tx(cli_host, ica_address, num_txs)
return str, diff_amt
Expand All @@ -133,14 +140,15 @@ def test_call(ibc):
contract_info = json.loads(CONTRACT_ABIS["IICAModule"].read_text())
contract = w3.eth.contract(address=CONTRACT, abi=contract_info)
data = {"from": ADDRS[name]}
channel_id = get_next_channel(cli_controller, connid)
ica_address = register_acc(
cli_controller,
w3,
contract.functions.registerAccount,
contract.functions.queryAccount,
data,
addr,
get_next_channel(cli_controller, connid),
channel_id,
)
balance = funds_ica(cli_host, ica_address)
expected_seq = 1
Expand All @@ -152,6 +160,7 @@ def test_call(ibc):
False,
expected_seq,
contract.events.SubmitMsgsResult,
channel_id=channel_id,
)
balance -= diff
assert cli_host.balance(ica_address, denom=denom) == balance
Expand All @@ -164,25 +173,31 @@ def test_call(ibc):
True,
expected_seq,
contract.events.SubmitMsgsResult,
channel_id=channel_id,
)
balance -= diff
assert cli_host.balance(ica_address, denom=denom) == balance


def wait_for_status_change(tcontract, seq):
def wait_for_status_change(tcontract, channel_id, seq):
print(f"wait for status change for {seq}")

def check_status():
status = tcontract.caller.statusMap(seq)
print("current", status)
status = tcontract.caller.getStatus(channel_id, seq)
return status

wait_for_fn("current status", check_status)


def wait_for_packet_log(start, event, seq, status):
def wait_for_packet_log(start, event, channel_id, seq, status):
print("wait for log arrive", seq, status)
expected = AttributeDict({"seq": seq, "status": status})
expected = AttributeDict(
{
"packetSrcChannel": keccak(text=channel_id),
"seq": seq,
"status": status,
}
)

def check_log():
logs = event.getLogs(fromBlock=start)
Expand Down Expand Up @@ -245,6 +260,7 @@ def submit_msgs_ro(func, str):
assert send_transaction(w3, tx, keys).status == 0

expected_seq = 1
packet_event = tcontract.events.OnPacketResult
start = w3.eth.get_block_number()
str, diff = submit_msgs(
ibc,
Expand All @@ -254,15 +270,16 @@ def submit_msgs_ro(func, str):
False,
expected_seq,
contract.events.SubmitMsgsResult,
channel_id=channel_id,
)
submit_msgs_ro(tcontract.functions.delegateSubmitMsgs, str)
submit_msgs_ro(tcontract.functions.staticSubmitMsgs, str)
last_seq = tcontract.caller.getLastSeq()
wait_for_status_change(tcontract, last_seq)
status = tcontract.caller.statusMap(last_seq)
wait_for_status_change(tcontract, channel_id, last_seq)
status = tcontract.caller.getStatus(channel_id, last_seq)
assert expected_seq == last_seq
assert status == Status.SUCCESS
wait_for_packet_log(start, tcontract.events.OnPacketResult, last_seq, status)
wait_for_packet_log(start, packet_event, channel_id, last_seq, status)
balance -= diff
assert cli_host.balance(ica_address, denom=denom) == balance

Expand All @@ -276,15 +293,16 @@ def submit_msgs_ro(func, str):
True,
expected_seq,
contract.events.SubmitMsgsResult,
channel_id=channel_id,
)
submit_msgs_ro(tcontract.functions.delegateSubmitMsgs, str)
submit_msgs_ro(tcontract.functions.staticSubmitMsgs, str)
last_seq = tcontract.caller.getLastSeq()
wait_for_status_change(tcontract, last_seq)
status = tcontract.caller.statusMap(last_seq)
wait_for_status_change(tcontract, channel_id, last_seq)
status = tcontract.caller.getStatus(channel_id, last_seq)
assert expected_seq == last_seq
assert status == Status.SUCCESS
wait_for_packet_log(start, tcontract.events.OnPacketResult, last_seq, status)
wait_for_packet_log(start, packet_event, channel_id, last_seq, status)
balance -= diff
assert cli_host.balance(ica_address, denom=denom) == balance

Expand All @@ -301,13 +319,14 @@ def submit_msgs_ro(func, str):
contract.events.SubmitMsgsResult,
amount=100000001,
need_wait=False,
channel_id=channel_id,
)
last_seq = tcontract.caller.getLastSeq()
wait_for_status_change(tcontract, last_seq)
status = tcontract.caller.statusMap(last_seq)
wait_for_status_change(tcontract, channel_id, last_seq)
status = tcontract.caller.getStatus(channel_id, last_seq)
assert expected_seq == last_seq
assert status == Status.FAIL
wait_for_packet_log(start, tcontract.events.OnPacketResult, last_seq, status)
wait_for_packet_log(start, packet_event, channel_id, last_seq, status)
assert cli_host.balance(ica_address, denom=denom) == balance

# balance should not change on timeout
Expand All @@ -325,25 +344,28 @@ def submit_msgs_ro(func, str):
contract.events.SubmitMsgsResult,
timeout,
msg_num=100,
channel_id=channel_id,
)
last_seq = tcontract.caller.getLastSeq()
wait_for_status_change(tcontract, last_seq)
status = tcontract.caller.statusMap(last_seq)
wait_for_status_change(tcontract, channel_id, last_seq)
status = tcontract.caller.getStatus(channel_id, last_seq)
assert expected_seq == last_seq
assert status == Status.FAIL
wait_for_packet_log(start, tcontract.events.OnPacketResult, last_seq, status)
wait_for_packet_log(start, packet_event, channel_id, last_seq, status)
assert cli_host.balance(ica_address, denom=denom) == balance
wait_for_check_channel_ready(cli_controller, connid, channel_id, "STATE_CLOSED")
data["gas"] = default_gas
channel_id2 = get_next_channel(cli_controller, connid)
ica_address2 = register_acc(
cli_controller,
w3,
tcontract.functions.callRegister,
contract.functions.queryAccount,
data,
addr,
get_next_channel(cli_controller, connid),
channel_id2,
)
assert channel_id2 != channel_id, channel_id2
assert ica_address2 == ica_address, ica_address2
expected_seq = 1
start = w3.eth.get_block_number()
Expand All @@ -355,13 +377,14 @@ def submit_msgs_ro(func, str):
False,
expected_seq,
contract.events.SubmitMsgsResult,
channel_id=channel_id2,
)
last_seq = tcontract.caller.getLastSeq()
wait_for_status_change(tcontract, last_seq)
status = tcontract.caller.statusMap(last_seq)
wait_for_status_change(tcontract, channel_id2, last_seq)
status = tcontract.caller.getStatus(channel_id2, last_seq)
assert expected_seq == last_seq
assert status == Status.SUCCESS
# wait for ack to add log from call evm
wait_for_packet_log(start, tcontract.events.OnPacketResult, last_seq, status)
wait_for_packet_log(start, packet_event, channel_id2, last_seq, status)
balance -= diff
assert cli_host.balance(ica_address, denom=denom) == balance

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading