Skip to content

Commit

Permalink
wormchain: add ibc_receiver_test and ict workflow (wormhole-foundatio…
Browse files Browse the repository at this point in the history
  • Loading branch information
kakucodes authored Dec 12, 2024
1 parent 996dabe commit 2306e2d
Show file tree
Hide file tree
Showing 15 changed files with 878 additions and 6 deletions.
63 changes: 63 additions & 0 deletions .github/workflows/wormchain-icts.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
name: Wormchain's end-to-end Interchain Tests

on:
pull_request:
push:
tags:
- "**"
branches:
- "main"

permissions:
contents: read
packages: write

env:
GO_VERSION: 1.21

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
e2e-tests:
runs-on: ubuntu-latest
strategy:
matrix:
# names of `make` commands to run tests
test:
- "ictest-cancel-upgrade"
- "ictest-upgrade"
- "ictest-wormchain"
- "ictest-ibc-receiver"
fail-fast: false

steps:
- name: Set up Go ${{ env.GO_VERSION }}
uses: actions/setup-go@v4
with:
go-version: ${{ env.GO_VERSION }}
cache-dependency-path: interchaintest/go.sum

- name: checkout chain
uses: actions/checkout@v4

- name: Run Test
id: run_test
continue-on-error: true
working-directory: wormchain
run: make ${{ matrix.test }}

- name: Retry Failed Test
if: steps.run_test.outcome == 'failure'
working-directory: wormchain
run: |
for i in 1 2; do
echo "Retry attempt $i"
if make ${{ matrix.test }}; then
echo "Test passed on retry"
exit 0
fi
done
echo "Test failed after retries"
exit 1
28 changes: 28 additions & 0 deletions wormchain/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -78,3 +78,31 @@ bootstrap:
clean:
rm -rf build/wormchaind build/wormchaind-* build/**/*.db build/**/*.wal vue
echo "{\"height\":\"0\",\"round\":0,\"step\":0}" > build/data/priv_validator_state.json

#####################
## INTERCHAINTESTS ##
#####################

# Individual Tests ($$ is interpreted as $)
rm-testcache:
go clean -testcache

ictest-cancel-upgrade: rm-testcache
cd interchaintest && go test -race -v -run ^TestCancelUpgrade$$ ./...

ictest-malformed-payload: rm-testcache
cd interchaintest && go test -race -v -run ^TestMalformedPayload$$ ./...

ictest-upgrade-failure: rm-testcache
cd interchaintest && go test -race -v -run ^TestUpgradeFailure$$ ./...

ictest-upgrade: rm-testcache
cd interchaintest && go test -race -v -run ^TestUpgrade$$ ./...

ictest-wormchain: rm-testcache
cd interchaintest && go test -race -v -run ^TestWormchain$$ ./...

ictest-ibc-receiver: rm-testcache
cd interchaintest && go test -race -v -run ^TestIbcReceiver ./...

.PHONY: ictest-cancel-upgrade ictest-malformed-payload ictest-upgrade-failure ictest-upgrade ictest-wormchain ictest-ibc-receiver
Binary file not shown.
Binary file not shown.
2 changes: 1 addition & 1 deletion wormchain/interchaintest/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ require (
github.com/ethereum/go-ethereum v1.11.6
github.com/strangelove-ventures/interchaintest/v4 v4.0.0-20230815125617-67bc301715ea
github.com/tendermint/crypto v0.0.0-20191022145703-50d29ede1e15
github.com/tendermint/tendermint v0.34.26
github.com/wormhole-foundation/wormhole/sdk v0.0.0-20230614161948-7f6213019abf
)

Expand Down Expand Up @@ -163,7 +164,6 @@ require (
github.com/subosito/gotenv v1.4.1 // indirect
github.com/syndtr/goleveldb v1.0.1-0.20220614013038-64ee5596c38a // indirect
github.com/tendermint/go-amino v0.16.0 // indirect
github.com/tendermint/tendermint v0.34.26 // indirect
github.com/tendermint/tm-db v0.6.7 // indirect
github.com/tidwall/btree v1.5.0 // indirect
github.com/vedhavyas/go-subkey v1.0.3 // indirect
Expand Down
16 changes: 16 additions & 0 deletions wormchain/interchaintest/helpers/instantiate_contract.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,3 +69,19 @@ func InstantiateContract(
type QueryContractResponse struct {
Contracts []string `json:"contracts"`
}

func StoreAndInstantiateWormholeContract(
t *testing.T,
ctx context.Context,
chain *cosmos.CosmosChain,
keyName string,
fileLoc string,
label string,
message string,
guardians *guardians.ValSet,
) (contract ContractInfoResponse) {
codeId := StoreContract(t, ctx, chain, keyName, fileLoc, guardians)
contractAddr := InstantiateContract(t, ctx, chain, keyName, codeId, label, message, guardians)

return QueryContractInfo(t, chain, ctx, contractAddr)
}
40 changes: 40 additions & 0 deletions wormchain/interchaintest/helpers/query_contract_info.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package helpers

import (
"context"
"encoding/json"
"testing"

"github.com/strangelove-ventures/interchaintest/v4/chain/cosmos"
"github.com/stretchr/testify/require"
)

// QueryContractInfo queries the information about a contract like the admin and code_id.
func QueryContractInfo(t *testing.T, chain *cosmos.CosmosChain, ctx context.Context, contractAddress string) ContractInfoResponse {
stdout, _, err := chain.GetFullNode().ExecQuery(ctx,
"wasm", "contract", contractAddress,
)
require.NoError(t, err)

res := new(ContractInfoResponse)
err = json.Unmarshal(stdout, res)
require.NoError(t, err)

return *res
}

type ContractInfoResponse struct {
Address string `json:"address"`
ContractInfo struct {
CodeID string `json:"code_id"`
Creator string `json:"creator"`
Admin string `json:"admin"`
Label string `json:"label"`
Created struct {
BlockHeight string `json:"block_height"`
TxIndex string `json:"tx_index"`
} `json:"created"`
IbcPortID string `json:"ibc_port_id"`
Extension any `json:"extension"`
} `json:"contract_info"`
}
5 changes: 0 additions & 5 deletions wormchain/interchaintest/helpers/store_contract.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,11 +61,6 @@ func createIbcReceiverUpdateChannelPayload(payload vaa.BodyIbcUpdateChannelChain
return gov_msg.MarshalBinary(), nil
}

// func UpgradeCoreContract(t *testing.T, ctx context.Context, chain *cosmos.CosmosChain, keyName string, payload vaa.BodyContractUpgrade, guardians *guardians.ValSet) {
// node := chain.GetFullNode()

// }

// wormchaind tx wormhole store [wasm file] [vaa-hex] [flags]
func StoreContract(t *testing.T, ctx context.Context, chain *cosmos.CosmosChain, keyName string, fileLoc string, guardians *guardians.ValSet) (codeId string) {
node := chain.GetFullNode()
Expand Down
96 changes: 96 additions & 0 deletions wormchain/interchaintest/helpers/utils.go
Original file line number Diff line number Diff line change
@@ -1,14 +1,21 @@
package helpers

import (
"context"
"fmt"
"slices"
"strconv"
"strings"
"testing"

"github.com/strangelove-ventures/interchaintest/v4/chain/cosmos"
"github.com/strangelove-ventures/interchaintest/v4/ibc"
"github.com/strangelove-ventures/interchaintest/v4/testreporter"
"github.com/strangelove-ventures/interchaintest/v4/testutil"

sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/stretchr/testify/require"
abcitypes "github.com/tendermint/tendermint/abci/types"
)

func MustAccAddressFromBech32(address string, bech32Prefix string) sdk.AccAddress {
Expand Down Expand Up @@ -45,3 +52,92 @@ func FindEventAttribute(t *testing.T, chain *cosmos.CosmosChain, txHash string,
fmt.Println("Not found: ", eventType, " ", attributeKey, " ", attributeValue, "!")
return false
}

// FindOpenChannelByVersion queries all the channels of a given chain and returns the first with the given version. If no channel is found, it will fail the test.
func FindOpenChannelByVersion(
t *testing.T,
ctx context.Context,
eRep *testreporter.RelayerExecReporter,
r ibc.Relayer,
chain *cosmos.CosmosChain,
version string) ibc.ChannelOutput {
// iterate up to 20 times to allow for chain to catch up
for i := 0; i < 20; i++ {

channels, err := r.GetChannels(ctx, eRep, chain.Config().ChainID)
require.NoError(t, err)

channelIdx := slices.IndexFunc(channels, func(channel ibc.ChannelOutput) bool {
return channel.State == "STATE_OPEN" && channel.Version == version
})
if channelIdx != -1 {
return channels[channelIdx]
}
testutil.WaitForBlocks(ctx, 1, chain)
}

require.Failf(t, "channel with version %s not found", version)
return ibc.ChannelOutput{}
}

func GetIBCTx(
c *cosmos.CosmosChain,
txHash string,
) (tx ibc.Tx, _ error) {
txResp, err := c.GetTransaction(txHash)
if err != nil {
return tx, fmt.Errorf("failed to get transaction %s: %w", txHash, err)
}
tx.Height = uint64(txResp.Height)
tx.TxHash = txHash
// In cosmos, user is charged for entire gas requested, not the actual gas used.
tx.GasSpent = txResp.GasWanted

const evType = "send_packet"
events := txResp.Events

var (
seq, _ = AttributeValue(events, evType, "packet_sequence")
srcPort, _ = AttributeValue(events, evType, "packet_src_port")
srcChan, _ = AttributeValue(events, evType, "packet_src_channel")
dstPort, _ = AttributeValue(events, evType, "packet_dst_port")
dstChan, _ = AttributeValue(events, evType, "packet_dst_channel")
timeoutHeight, _ = AttributeValue(events, evType, "packet_timeout_height")
timeoutTs, _ = AttributeValue(events, evType, "packet_timeout_timestamp")
data, _ = AttributeValue(events, evType, "packet_data")
)
tx.Packet.SourcePort = srcPort
tx.Packet.SourceChannel = srcChan
tx.Packet.DestPort = dstPort
tx.Packet.DestChannel = dstChan
tx.Packet.TimeoutHeight = timeoutHeight
tx.Packet.Data = []byte(data)

seqNum, err := strconv.Atoi(seq)
if err != nil {
return tx, fmt.Errorf("invalid packet sequence from events %s: %w", seq, err)
}
tx.Packet.Sequence = uint64(seqNum)

timeoutNano, err := strconv.ParseUint(timeoutTs, 10, 64)
if err != nil {
return tx, fmt.Errorf("invalid packet timestamp timeout %s: %w", timeoutTs, err)
}
tx.Packet.TimeoutTimestamp = ibc.Nanoseconds(timeoutNano)

return tx, nil
}

func AttributeValue(events []abcitypes.Event, eventType, attrKey string) (string, bool) {
for _, event := range events {
if event.Type != eventType {
continue
}
for _, attr := range event.Attributes {
if string(attr.Key) == attrKey {
return string(attr.Value), true
}
}
}
return "", false
}
11 changes: 11 additions & 0 deletions wormchain/interchaintest/helpers/vaa.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,14 @@ func generateVaa(index uint32, signers *guardians.ValSet, emitterChain vaa.Chain
latestSequence = latestSequence + 1
return signVaa(v, signers)
}

func GenerateGovernanceVaa(index uint32,
signers *guardians.ValSet,
payload []byte) vaa.VAA {

v := vaa.CreateGovernanceVAA(time.Unix(0, 0),
uint32(1), uint64(latestSequence), index, payload)

latestSequence = latestSequence + 1
return signVaa(*v, signers)
}
61 changes: 61 additions & 0 deletions wormchain/interchaintest/helpers/wormchain_ibc_receiver/helpers.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package wormchain_ibc_receiver

import (
"encoding/base64"
"encoding/json"
"testing"

"github.com/stretchr/testify/require"
"github.com/wormhole-foundation/wormchain/interchaintest/guardians"
"github.com/wormhole-foundation/wormchain/interchaintest/helpers"
"github.com/wormhole-foundation/wormhole/sdk/vaa"
)

func SubmitIbcReceiverUpdateChannelChainMsg(t *testing.T,
allowlistChainID vaa.ChainID,
allowlistChannel string,
guardians *guardians.ValSet) string {

paddedChannel, _ := vaa.LeftPadIbcChannelId(allowlistChannel)

bodyIbcReceiverUpdateChannelChain := vaa.BodyIbcUpdateChannelChain{
TargetChainId: vaa.ChainIDWormchain,
ChannelId: paddedChannel,
ChainId: allowlistChainID,
}

payload, err := bodyIbcReceiverUpdateChannelChain.Serialize(vaa.IbcReceiverModuleStr)
require.NoError(t, err)

v := helpers.GenerateGovernanceVaa(0, guardians, payload)
vBz, err := v.Marshal()
require.NoError(t, err)
vHex := base64.StdEncoding.EncodeToString(vBz)

var vaas [1]Binary
vaas[0] = Binary(vHex)

submitVAAMsg := ExecuteMsg{
SubmitUpdateChannelChain: &ExecuteMsg_SubmitUpdateChannelChain{
Vaas: vaas[:],
},
}

submitVAAMsgBz, err := json.Marshal(submitVAAMsg)
require.NoError(t, err)

return string(submitVAAMsgBz)
}

type ReceiverAck struct {
Ok *struct{} `json:"ok,omitempty"`
Error string `json:"error,omitempty"`
}

func (r ReceiverAck) IsOk() bool {
return len(r.Error) == 0
}

func (r ReceiverAck) IsError() bool {
return len(r.Error) > 0
}
Loading

0 comments on commit 2306e2d

Please sign in to comment.