Skip to content

Commit

Permalink
Complete IBC integration tests
Browse files Browse the repository at this point in the history
  • Loading branch information
ethanfrey committed Jan 18, 2021
1 parent bba25e2 commit 4bcc5a1
Show file tree
Hide file tree
Showing 2 changed files with 160 additions and 7 deletions.
30 changes: 25 additions & 5 deletions api/mocks.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,18 +61,38 @@ func MockInfoBin(t *testing.T, sender types.HumanAddress) []byte {

func MockIBCChannel(channelID string, ordering types.IBCOrder, ibcVersion string) types.IBCChannel {
return types.IBCChannel{
Endpoint: types.IBCEndpoint{
Endpoint: types.IBCEndpoint{
PortID: "my_port",
ChannelID: channelID,
},
CounterpartyEndpoint: types.IBCEndpoint{
PortID: "their_port",
ChannelID: "channel-7",
},
Order: ordering,
Version: ibcVersion,
CounterpartyVersion: ibcVersion,
ConnectionID: "connection-3",
Order: ordering,
Version: ibcVersion,
CounterpartyVersion: ibcVersion,
ConnectionID: "connection-3",
}
}

func MockIBCPacket(myChannel string, data []byte) types.IBCPacket {
return types.IBCPacket{
Data: data,
Src: types.IBCEndpoint{
PortID: "their_port",
ChannelID: "channel-7",
},
Dest: types.IBCEndpoint{
PortID: "my_port",
ChannelID: myChannel,
},
Sequence: 15,
TimeoutHeight: &types.IBCTimeoutHeight{
RevisionNumber: 1,
TimeoutHeight: 123456,
},
TimeoutTimestamp: nil,
}
}

Expand Down
137 changes: 135 additions & 2 deletions ibc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,41 @@ type IBCInitMsg struct {
ReflectCodeID uint64 `json:"reflect_code_id"`
}

type IBCHandleMsg struct {
InitCallback InitCallback `json:"init_callback"`
}

type InitCallback struct {
ID string `json:"id"`
ContractAddr string `json:"contract_addr"`
}

type IBCPacketMsg struct {
Dispatch *DispatchMsg `json:"dispatch,omitempty"`
}

type DispatchMsg struct {
Msgs []types.CosmosMsg `json:"msgs"`
}

type IBCQueryMsg struct {
ListAccounts *struct{} `json:"list_accounts,omitempty"`
}

type ListAccountsResponse struct {
Accounts []AccountInfo `json:"accounts"`
}

type AccountInfo struct {
Account string `json:"account"`
ChannelID string `json:"channel_id"`
}

// We just check if an error is returned or not
type AcknowledgeDispatch struct {
Err string `json:"error"`
}

func toBytes(t *testing.T, v interface{}) []byte {
bz, err := json.Marshal(v)
require.NoError(t, err)
Expand All @@ -39,8 +74,6 @@ func toBytes(t *testing.T, v interface{}) []byte {
func TestIBCHandshake(t *testing.T) {
// code id of the reflect contract
const REFLECT_ID uint64 = 101
// address of first reflect contract instance that we created
const REFLECT_ADDR = "reflect-acct-1"
// channel id for handshake
const CHANNEL_ID = "channel-432"

Expand Down Expand Up @@ -95,3 +128,103 @@ func TestIBCHandshake(t *testing.T) {
assert.Equal(t, REFLECT_ID, init.CodeID)
assert.Empty(t, init.Send)
}

func TestIBCPacketDispatch(t *testing.T) {
// code id of the reflect contract
const REFLECT_ID uint64 = 77
// address of first reflect contract instance that we created
const REFLECT_ADDR = "reflect-acct-1"
// channel id for handshake
const CHANNEL_ID = "channel-234"

// setup
vm := withVM(t)
id := createTestContract(t, vm, IBC_TEST_CONTRACT)
gasMeter1 := api.NewMockGasMeter(TESTING_GAS_LIMIT)
// instantiate it with this store
store := api.NewLookup(gasMeter1)
goapi := api.NewMockAPI()
balance := types.Coins{}
querier := api.DefaultQuerier(api.MOCK_CONTRACT_ADDR, balance)

// init
env := api.MockEnv()
info := api.MockInfo("creator", nil)
initMsg := IBCInitMsg{
ReflectCodeID: REFLECT_ID,
}
_, _, err := vm.Instantiate(id, env, info, toBytes(t, initMsg), store, *goapi, querier, gasMeter1, TESTING_GAS_LIMIT)
require.NoError(t, err)

// channel open
gasMeter2 := api.NewMockGasMeter(TESTING_GAS_LIMIT)
store.SetGasMeter(gasMeter2)
channel := api.MockIBCChannel(CHANNEL_ID, types.Ordered, "ibc-reflect")
channel.CounterpartyVersion = ""
_, err = vm.IBCChannelOpen(id, env, channel, store, *goapi, querier, gasMeter2, TESTING_GAS_LIMIT)
require.NoError(t, err)

// channel connect
gasMeter3 := api.NewMockGasMeter(TESTING_GAS_LIMIT)
store.SetGasMeter(gasMeter3)
// completes and dispatches message to create reflect contract
channel = api.MockIBCChannel(CHANNEL_ID, types.Ordered, "ibc-reflect")
_, _, err = vm.IBCChannelConnect(id, env, channel, store, *goapi, querier, gasMeter3, TESTING_GAS_LIMIT)
require.NoError(t, err)

// mock reflect init callback (to store address)
gasMeter4 := api.NewMockGasMeter(TESTING_GAS_LIMIT)
store.SetGasMeter(gasMeter4)
handleMsg := IBCHandleMsg{
InitCallback: InitCallback{
ID: CHANNEL_ID,
ContractAddr: REFLECT_ADDR,
},
}
info = api.MockInfo(REFLECT_ADDR, nil)
_, _, err = vm.Execute(id, env, info, toBytes(t, handleMsg), store, *goapi, querier, gasMeter4, TESTING_GAS_LIMIT)
require.NoError(t, err)

// ensure the channel is registered
queryMsg := IBCQueryMsg{
ListAccounts: &struct{}{},
}
qres, _, err := vm.Query(id, env, toBytes(t, queryMsg), store, *goapi, querier, gasMeter4, TESTING_GAS_LIMIT)
require.NoError(t, err)
var accounts ListAccountsResponse
err = json.Unmarshal(qres, &accounts)
require.Equal(t, 1, len(accounts.Accounts))
require.Equal(t, CHANNEL_ID, accounts.Accounts[0].ChannelID)
require.Equal(t, REFLECT_ADDR, accounts.Accounts[0].Account)

// process message received on this channel
gasMeter5 := api.NewMockGasMeter(TESTING_GAS_LIMIT)
store.SetGasMeter(gasMeter5)
ibcMsg := IBCPacketMsg{
Dispatch: &DispatchMsg{
Msgs: []types.CosmosMsg{{
Bank: &types.BankMsg{Send: &types.SendMsg{
ToAddress: "my-friend",
Amount: types.Coins{types.NewCoin(12345678, "uatom")},
}},
}},
},
}
packet := api.MockIBCPacket(CHANNEL_ID, toBytes(t, ibcMsg))
pres, _, err := vm.IBCPacketReceive(id, env, packet, store, *goapi, querier, gasMeter5, TESTING_GAS_LIMIT)
require.NoError(t, err)

// assert app-level success
var ack AcknowledgeDispatch
err = json.Unmarshal(pres.Acknowledgement, &ack)
require.Empty(t, ack.Err)

// error on message from another channel
packet2 := api.MockIBCPacket("no-such-channel", toBytes(t, ibcMsg))
pres2, _, err := vm.IBCPacketReceive(id, env, packet2, store, *goapi, querier, gasMeter5, TESTING_GAS_LIMIT)
require.NoError(t, err)
// assert app-level failure
var ack2 AcknowledgeDispatch
err = json.Unmarshal(pres2.Acknowledgement, &ack2)
require.Equal(t, "invalid packet: cosmwasm_std::addresses::HumanAddr not found", ack2.Err)
}

0 comments on commit 4bcc5a1

Please sign in to comment.