Skip to content

Commit

Permalink
fix: ibc-hooks transfer stack order and add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
emidev98 committed Nov 2, 2023
1 parent abd6fe1 commit 763e9ef
Show file tree
Hide file tree
Showing 22 changed files with 1,072 additions and 67 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,5 @@ bin
*/.DS_Store


scripts/tests/ibc-hooks/counter/target
data
24 changes: 24 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -92,3 +92,27 @@ install: go.sum

build:
go build $(BUILD_FLAGS) -o bin/migalood ./cmd/migalood

integration-test-all: init-test-framework \
test-relayer \
test-ibc-hooks

init-test-framework: clean-testing-data install
@echo "Initializing both blockchains..."
./scripts/tests/init-test-framework.sh

test-relayer:
@echo "Testing relayer..."
./scripts/tests/relayer/interchain-acc-config/rly-init.sh

test-ibc-hooks:
@echo "Testing ibc hooks..."
./scripts/tests/ibc-hooks/increment.sh

clean-testing-data:
@echo "Killing migalood and removing previous data"
-@pkill migalood 2>/dev/null
-@pkill rly 2>/dev/null
-@rm -rf ./data

.PHONY: all install build integration-test-all init-test-framework test-relayer test-ibc-hooks clean-testing-data
123 changes: 56 additions & 67 deletions app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,7 @@ type MigalooApp struct {

// IBC hooks
IBCHooksKeeper *ibchookskeeper.Keeper
TransferStack *ibchooks.IBCMiddleware
TransferStack porttypes.Middleware
Ics20WasmHooks *ibchooks.WasmHooks
HooksICS4Wrapper ibchooks.ICS4Middleware

Expand Down Expand Up @@ -518,18 +518,6 @@ func NewMigalooApp(
AddRoute(ibcclienttypes.RouterKey, ibcclient.NewClientProposalHandler(app.IBCKeeper.ClientKeeper)).
AddRoute(alliancemoduletypes.RouterKey, alliancemodule.NewAllianceProposalHandler(app.AllianceKeeper))

// RouterKeeper must be created before TransferKeeper
app.RouterKeeper = *routerkeeper.NewKeeper(
appCodec,
app.keys[routertypes.StoreKey],
app.GetSubspace(routertypes.ModuleName),
app.TransferKeeper,
app.IBCKeeper.ChannelKeeper,
app.DistrKeeper,
app.BankKeeper,
app.IBCKeeper.ChannelKeeper,
)

// Configure the hooks keeper
hooksKeeper := ibchookskeeper.NewKeeper(
keys[ibchookstypes.StoreKey],
Expand All @@ -543,38 +531,47 @@ func NewMigalooApp(
app.Ics20WasmHooks,
)

// IBC Fee Module keeper
app.IBCFeeKeeper = ibcfeekeeper.NewKeeper(
appCodec, keys[ibcfeetypes.StoreKey],
app.IBCKeeper.ChannelKeeper, // may be replaced with IBC middleware
app.IBCKeeper.ChannelKeeper,
&app.IBCKeeper.PortKeeper, app.AccountKeeper, app.BankKeeper,
)

// Create Transfer Keepers
app.TransferKeeper = ibctransferkeeper.NewKeeper(
appCodec,
keys[ibctransfertypes.StoreKey],
app.GetSubspace(ibctransfertypes.ModuleName),
app.IBCFeeKeeper, // ISC4 Wrapper: fee IBC middleware
app.HooksICS4Wrapper,
app.IBCKeeper.ChannelKeeper,
&app.IBCKeeper.PortKeeper,
app.AccountKeeper,
app.BankKeeper,
scopedTransferKeeper,
)
transferIBCModule := transfer.NewIBCModule(app.TransferKeeper)

app.RouterKeeper.SetTransferKeeper(app.TransferKeeper)
// Hooks Middleware
hooksTransferStack := ibchooks.NewIBCMiddleware(&transferIBCModule, &app.HooksICS4Wrapper)

// ICA Host keeper
app.ICAHostKeeper = icahostkeeper.NewKeeper(
appCodec, keys[icahosttypes.StoreKey], app.GetSubspace(icahosttypes.SubModuleName),
app.IBCFeeKeeper, // use ics29 fee as ics4Wrapper in middleware stack
app.IBCKeeper.ChannelKeeper, &app.IBCKeeper.PortKeeper,
app.AccountKeeper, scopedICAHostKeeper, app.MsgServiceRouter(),
app.RouterKeeper = *routerkeeper.NewKeeper(
appCodec,
app.keys[routertypes.StoreKey],
app.GetSubspace(routertypes.ModuleName),
app.TransferKeeper,
app.IBCKeeper.ChannelKeeper,
app.DistrKeeper,
app.BankKeeper,
app.IBCKeeper.ChannelKeeper,
)
icaModule := ica.NewAppModule(nil, &app.ICAHostKeeper)
pmfTransferStack := router.NewIBCMiddleware(hooksTransferStack,
&app.RouterKeeper,
5,
routerkeeper.DefaultForwardTransferPacketTimeoutTimestamp,
routerkeeper.DefaultRefundTransferPacketTimeoutTimestamp,
)
app.TransferStack = &pmfTransferStack

app.IBCFeeKeeper = ibcfeekeeper.NewKeeper(
appCodec, keys[ibcfeetypes.StoreKey],
app.IBCKeeper.ChannelKeeper, // may be replaced with IBC middleware
app.IBCKeeper.ChannelKeeper,
&app.IBCKeeper.PortKeeper, app.AccountKeeper, app.BankKeeper,
)
app.ICAControllerKeeper = icacontrollerkeeper.NewKeeper(
appCodec,
keys[icacontrollertypes.StoreKey],
Expand All @@ -585,9 +582,34 @@ func NewMigalooApp(
scopedICAControllerKeeper,
app.MsgServiceRouter(),
)
app.ICAHostKeeper = icahostkeeper.NewKeeper(
appCodec,
keys[icahosttypes.StoreKey],
app.GetSubspace(icahosttypes.SubModuleName),
app.IBCFeeKeeper, // use ics29 fee as ics4Wrapper in middleware stack
app.IBCKeeper.ChannelKeeper,
&app.IBCKeeper.PortKeeper,
app.AccountKeeper,
scopedICAHostKeeper,
app.MsgServiceRouter(),
)
icaModule := ica.NewAppModule(nil, &app.ICAHostKeeper)

// For wasmd we use the demo controller from https://github.com/cosmos/interchain-accounts but see notes below
app.InterTxKeeper = intertxkeeper.NewKeeper(appCodec, keys[intertxtypes.StoreKey], app.ICAControllerKeeper, scopedInterTxKeeper)
app.InterTxKeeper = intertxkeeper.NewKeeper(
appCodec,
keys[intertxtypes.StoreKey],
app.ICAControllerKeeper,
scopedInterTxKeeper,
)

var icaControllerStack porttypes.IBCModule
icaControllerStack = intertx.NewIBCModule(app.InterTxKeeper)
icaControllerStack = icacontroller.NewIBCMiddleware(icaControllerStack, app.ICAControllerKeeper)
icaControllerStack = ibcfee.NewIBCMiddleware(icaControllerStack, app.IBCFeeKeeper)

icaHostIBCModule := icahost.NewIBCModule(app.ICAHostKeeper)
icaHostStack := ibcfee.NewIBCMiddleware(icaHostIBCModule, app.IBCFeeKeeper)

// create evidence keeper with router
evidenceKeeper := evidencekeeper.NewKeeper(
Expand Down Expand Up @@ -635,51 +657,18 @@ func NewMigalooApp(
govRouter.AddRoute(wasm.RouterKey, wasm.NewWasmProposalHandler(app.WasmKeeper, enabledProposals))
}

// Create Transfer Stack
var transferStack porttypes.IBCModule
transferStack = transfer.NewIBCModule(app.TransferKeeper)
transferStack = ibcfee.NewIBCMiddleware(transferStack, app.IBCFeeKeeper)
transferStack = router.NewIBCMiddleware(
transferStack,
&app.RouterKeeper,
0,
routerkeeper.DefaultForwardTransferPacketTimeoutTimestamp,
routerkeeper.DefaultRefundTransferPacketTimeoutTimestamp,
)
// Hooks Middleware
hooksTransferStack := ibchooks.NewIBCMiddleware(transferStack, &app.HooksICS4Wrapper)
app.TransferStack = &hooksTransferStack

// Create Interchain Accounts Stack
// SendPacket, since it is originating from the application to core IBC:
// icaAuthModuleKeeper.SendTx -> icaController.SendPacket -> fee.SendPacket -> channel.SendPacket

// Note: please do your research before using this in production app, this is a demo and not an officially
// supported IBC team implementation. Do your own research before using it.
var icaControllerStack porttypes.IBCModule
// You will likely want to use your own reviewed and maintained ica auth module
icaControllerStack = intertx.NewIBCModule(app.InterTxKeeper)
icaControllerStack = icacontroller.NewIBCMiddleware(icaControllerStack, app.ICAControllerKeeper)
icaControllerStack = ibcfee.NewIBCMiddleware(icaControllerStack, app.IBCFeeKeeper)

// RecvPacket, message that originates from core IBC and goes down to app, the flow is:
// channel.RecvPacket -> fee.OnRecvPacket -> icaHost.OnRecvPacket
var icaHostStack porttypes.IBCModule
icaHostStack = icahost.NewIBCModule(app.ICAHostKeeper)
icaHostStack = ibcfee.NewIBCMiddleware(icaHostStack, app.IBCFeeKeeper)

// Create fee enabled wasm ibc Stack
var wasmStack porttypes.IBCModule
wasmStack = wasm.NewIBCHandler(app.WasmKeeper, app.IBCKeeper.ChannelKeeper, app.IBCFeeKeeper)
wasmStack = ibcfee.NewIBCMiddleware(wasmStack, app.IBCFeeKeeper)

// Create static IBC router, add app routes, then set and seal it
ibcRouter := porttypes.NewRouter().
AddRoute(ibctransfertypes.ModuleName, transferStack).
AddRoute(wasm.ModuleName, wasmStack).
AddRoute(intertxtypes.ModuleName, icaControllerStack).
AddRoute(icacontrollertypes.SubModuleName, icaControllerStack).
AddRoute(icahosttypes.SubModuleName, icaHostStack)
AddRoute(icahosttypes.SubModuleName, icaHostStack).
AddRoute(ibctransfertypes.ModuleName, pmfTransferStack).
AddRoute(wasm.ModuleName, wasmStack)
app.IBCKeeper.SetRouter(ibcRouter)

govConfig := govtypes.DefaultConfig()
Expand Down
15 changes: 15 additions & 0 deletions scripts/tests/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Tests

This folder contains the integration tests that should run successfully each time a new core release is created.

At the moment, there are four tests defined that can be run with `make integration-test-all`. The breakdown of each test is as follows:

- [init-test-framework](./start.sh): build the core and spin up two nodes with their own genesis event and some accounts preloaded with funds.
- [test-relayer](./relayer/): connect the two blockchains with a relayer opening a channel between both of them.
- [test-ica](./ica/delegate.sh): using the relayer, this test creates an interchain account and delegates funds using an interchain message.
- [test-ibc-hooks](./ibc-hooks/increment.sh): deploys a slightly modified [counter contract](./ibc-hooks/counter/) to chain test-2 and submits two requests from chain test-1 to validate that the contract received the funds and executed the wasm code correctly.
- remove-ica-data: removes the data and kills the process when the integration tests are completed.

## Development process

This set of tests must run out of the box in Linux-based systems installing [GoLang 1.20](https://go.dev/), [jq](https://stedolan.github.io/jq/), [screen](https://www.geeksforgeeks.org/screen-command-in-linux-with-examples/) and [rly](https://github.com/cosmos/relayer).
43 changes: 43 additions & 0 deletions scripts/tests/ibc-hooks/counter/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
[package]
name = "counter"
description = "Cosmwasm counter dapp, with permissions for testing Osmosis wasmhooks"
version = "0.1.0"
authors = ["osmosis contributors"]
edition = "2021"

exclude = [
# Those files are rust-optimizer artifacts. You might want to commit them for convenience but they should not be part of the source code publication.
"contract.wasm",
"hash.txt",
]

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[lib]
crate-type = ["cdylib", "rlib"]

[features]
# for more explicit tests, cargo test --features=backtraces
backtraces = ["cosmwasm-std/backtraces"]
# use library feature to disable all instantiate/execute/query exports
library = []

[package.metadata.scripts]
optimize = """docker run --rm -v "$(pwd)":/code \
--mount type=volume,source="$(basename "$(pwd)")_cache",target=/code/target \
--mount type=volume,source=registry_cache,target=/usr/local/cargo/registry \
cosmwasm/rust-optimizer:0.12.6
"""

[dependencies]
cosmwasm-schema = "1.1.3"
cosmwasm-std = "1.1.3"
cosmwasm-storage = "1.1.3"
cw-storage-plus = "0.16.0"
cw2 = "0.16.0"
schemars = "0.8.10"
serde = { version = "1.0.145", default-features = false, features = ["derive"] }
thiserror = { version = "1.0.31" }

[dev-dependencies]
cw-multi-test = "0.16.0"
11 changes: 11 additions & 0 deletions scripts/tests/ibc-hooks/counter/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Counter contract from [Osmosis Labs](https://github.com/osmosis-labs/osmosis/commit/64393a14e18b2562d72a3892eec716197a3716c7)

This contract is a modification of the standard cosmwasm `counter` contract.
Namely, it tracks a counter, _by sender_.
This is a better way to test wasmhooks.

This contract tracks any funds sent to it by adding it to the state under the `sender` key.

This way we can verify that, independently of the sender, the funds will end up under the
`WasmHooksModuleAccount` address when the contract is executed via an IBC send that goes
through the wasmhooks module.
1 change: 1 addition & 0 deletions scripts/tests/ibc-hooks/counter/artifacts/checksums.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
c0e7a3b40d9710f6f72322293ba5cd871714008d9accd9a91c0fb08272609054 counter.wasm
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
bffb3256d4fd5668e497ae5671844ef3dcdf1a5f2594747b894dfc02e243ab0e ./target/wasm32-unknown-unknown/release/counter.wasm
Binary file not shown.
Loading

0 comments on commit 763e9ef

Please sign in to comment.